2010-10-04 2 views
1

Je convertis un projet web qui utilise actuellement le Propel ORM, dans un projet django.Comment écrire cette classe pour le modèle de données de Django (conversion du format YML de Propel)

Ma première tâche est de 'porter' le schéma du modèle à django.

J'ai lu les documents django, mais ils ne semblent pas être suffisamment détaillés. comme suit le cas au point, comment peut I 'port' un (artificiel) table définie dans le schéma Propel YML:

demo_ref_country: 
    code:    { type: varchar(4), required: true, index: unique } 
    name:    { type: varchar(64), required: true, index: unique } 
    geog_region_id: { type: integer, foreignTable: demo_ref_geographic_region, foreignReference: id, required: true, onUpdate: cascade, onDelete: restrict } 
    ccy_id:   { type: integer, foreignTable: demo_ref_currency_def, foreignReference: id, required: true, onUpdate: cascade, onDelete: restrict } 
    flag_image_path: { type: varchar(64), required: true, default: ''} 
    created_at: ~ 

    _indexes: 

     idx_f1:   [geog_region_id, ccy_id, created_at] 

    _uniques: 

     idxu_f1_key: [code, geog_region_id, ccy_id] 

Voici mon (faible) tente jusqu'à présent:

class Country(models.Model): 
    code = models.CharField(max_length=4) # Erm, no index on this column ..... 
    name = models.CharField(max_length=64) # Erm, no index on this column ..... 
    geog_region_id = models.ForeignKey(GeogRegion) # Is this correct ? (how about ref integrity constraints ? 
    ccy_id = models.ForeignKey(Currency) # Is this correct? 
    flag_image_path = models.CharField(max_length=64) # How to set default on this col? 
    created_at = models.DateTimeField() # Will this default to now() ? 
    # Don't know how to specify indexes and unique indexes .... 

[ Edit]

Pour tous ceux qui suggèrent que je RTFM, je comprends votre frustration. C'est juste que la documentation n'est pas très claire pour moi. C'est probablement une méthode de documentation Pythonienne - mais venant d'un arrière-plan C++, je pense que la documentation pourrait être améliorée pour la rendre plus accessible aux personnes venant de différentes langues. Exemple: la documentation indique simplement le nom de la classe et un paramètre ** options dans le ctor, mais ne vous dit pas quelles sont les options possibles.

Par exemple classe CharField (max_length = Aucun, [options] **)

Il y a une ligne plus haut dans la documentation qui donne une liste des options autorisées, qui sont applicables à tous les types de terrain.

Cependant, les options sont présentées sous la forme:

Field.optionname

Le lien (apparemment implicite) entre une propriété de classe et un argument de constructeur n'a pas été clair pour moi. Il semble que si une classe a une propriété foo, cela signifie que vous pouvez passer un argument nommé foo à son constructeur. Cette observation est-elle vraie pour toutes les classes Python?

Répondre

0
Class demo_ref_country(models.Model) 
    code= models.CharField(max_length=4, db_index=True, null=False) 
    name= models.CharField(max_length=64, db_index=True, null=False) 
    geog_region = models.ForeignKey(geographic_region, null=False) 
    ccy = models.ForeignKey(Currency_def, null=False) 
    flag = models.ImageField(upload_to='path to directory', null=False, default="home") 
    created_at = models.DateTimeField(auto_now_add=True, db_index=True) 

class Meta: 
    unique_together = (code, geog_region, ccy) 

Vous pouvez définir des valeurs par défaut ,, db_index paramaeter crée des index pour les champs connexes. Vous pouvez utiliser unique = Vrai pour les champs séparés, mais un seul ensemble unique vérifiera l'unicité dans les colonnes ensemble.

MISE À JOUR: Tout d'abord, je vous conseille de lire attentivement documentatin, puisque django vous donne beaucoup de nouvelles chances, certains d'entre eux ont des restrictions ... comme option unique_together est utilisé juste pour django admin. Cela signifie que si vous créez un nouvel enregistrement ou le modifiez via l'interface d'administration, il sera utilisé. Si vous alsa insérer des données avec d'autres moyens (comme une déclaration DataModel.objects.create) son mieux vous utiliser uniaue = True dans la définition du champ comme:

code= models.CharField(max_length=4, db_index=True, null=False, unique=True) 

champs ForeignKey sont uniques par défaut, de sorte que vous n'avez pas besoin pour définir l'unicité pour eux. Django prend en charge le remplacement de méthode, de sorte que vous pouvez remplacer les méthodes d'enregistrement et de suppression de modèle comme vous le souhaitez. check it here. Django vous permet également d'écrire des requêtes sql crues you can check it here

Comme je l'ai expliqué, unique ensemble est une fonction d'administration django. Alors n'oubliez pas d'ajouter unique = True aux champs obligatoires. Unique ensemble vous permet également de définir différentes paires uniques, telles que;

unique_together = (('id','code'),('code','ccy','geog_region')) 

Cela signifie, id et code doit être unique ensemble et le code, CCY et geog_region doivent être uniques ensemble

MISE À JOUR 2: Avant votre mise à jour de question ...

Il est mieux vaut commencer par tutorials. Il définit les bases avec de bons exemples.

En ce qui concerne le style de doc, laissez-moi vous donner un exemple, mais si vous commencez des tuteurs, il sera plus facile pour vous ... Il y a de la structure modèle ... Doc here

BooleanField 

class BooleanField(**options) 

que définit, la structure de base d'un champ de base de données,() est utilisée et certains paramètres sont pris en option. qui est la partie:

models.BooleansField() 

Puisque c'est un struvture sur le terrain, les options disponibles sont définit comme:

unique 

Field.unique 

Ainsi,

models.BooleansField(unique=True) 

C'est l'usage général. Puisque uniqu est une option de base disponible pour tous les types de champs, elle est classée comme field.unique. Il y a quelques options disponibles à un seul type de champ, comme symétrique est une option de champ ManyToMany, est classé comme ManyToMany.Symmetrical

Pour la queryset

class QuerySet([model=None]) 

qui est utilisé comme vous utilisez une fonction, mais vous l'utiliser pour filtrer un modèle, avec d'autres mots, écrire une requête de filtre pour exécuter ... il a des méthodes, comme filtre ...

filter(**kwargs) 

Depuis cela prend quelques kwargs, et comme je l'ai dit avant, ceci est utilisé pour filtrer les résultats de vos requêtes, donc kwargs doit être vos champs de modèle (champs de table de base de données) comme:

MyModel.objects.filter(id=15) 

quel objet est définit dans le document, mais il est un gestionnaire qui vous aide à obtenir des objets liés.

Doc contient de bons exemples, mais vous devez commencer à partir de tuteurs, c'est ce que je peux vous conseiller ...

+0

Merci pour l'extrait. Je peux maintenant voir comment tout cela s'accorde. – skyeagle

+0

existe-t-il un moyen d'appliquer RI (intégrité référentielle) sur les insertions et les suppressions (c'est-à-dire en cascade etc.), comme je le fais dans le fichier de schéma Propel YML? – skyeagle

+0

Est-ce que unique_together est un mot-clé ?. Si oui, que se passe-t-il si vous avez plus d'un index clusterisé (clé multiple) sur une table? – skyeagle

1

Les index sont générés automatiquement pour vos références à d'autres modèles (c'est-à-dire vos clés étrangères). En d'autres termes: votre geog_region_id est correct (mais il serait préférable de l'appeler geog_region).

Vous pouvez définir des valeurs par défaut à l'aide de default field option.

+0

Merci pour vos commentaires. De ce que je comprends, je ne peux pas définir une colonne et spécifier un index, et ou une valeur par défaut en même temps comme je peux utiliser le format YML pour Propel. Il semble que je devrai décomposer ces déclarations en leurs parties constituantes (définition de colonne, puis création d'index, définition de valeurs par défaut, etc.). Est-ce que ma compréhension est correcte? – skyeagle

1

Je suis désolé, vous n'avez pas lu les documents. Une simple recherche de index, unique ou default sur le field reference page indique exactement comment définir ces options.

Editer après un commentaire Je ne comprends pas ce que vous entendez par lignes multiples. Python ne se soucie pas combien de lignes que vous utilisez entre parenthèses - donc ceci:

name = models.CharField(unique=True, db_index=True) 

est exactement la même que celle-ci:

name = models.CharField(
      unique=True, 
      db_index=True 
     ) 

Django ne supporte pas les clés primaires à plusieurs colonnes, mais si vous voulez juste une contrainte unique sur plusieurs colonnes, voir unique_together.

+1

J'ai déjà vu et lu cette page. Tous les exemples que j'avais vus jusqu'à présent avaient des colonnes de table définies avec 1 ligne d'instructions. Je m'attendais donc à ce qu'une colonne puisse être définie (y compris l'index) en une ligne - il semble que vous ne pouvez pas le faire, et que vous deviez décomposer l'instruction en plusieurs instructions (une pour le type de données et une autre pour l'index) lors de l'utilisation du framework Model de Django. En ce qui concerne les indixes multi-colonnes, je ne trouve toujours pas cela dans la documentation - pouvez-vous me montrer un exemple d'index multi-colonnes? – skyeagle

1
import datetime 
class Country(models.Model): 
    code = models.CharField(max_length=4, unique=True) 
    name = models.CharField(max_length=64) 
    geog_region = models.ForeignKey(GeogRegion) 
    ccy = models.ForeignKey(Currency, unique=True) 
    flag_image_path = models.CharField(max_length=64, default='') 
    created_at = models.DateTimeField(default=datetime.now()) 

(Je ne suis pas expert sur ORM Propel)

Django essaie toujours d'imiter le comportement « cascade sur suppression », donc pas besoin de préciser que quelque part. Par défaut, tous les champs sont obligatoires, sauf indication contraire. Pour le champ date/heure, consultez d'autres options here. Toutes les options de champ générales here.

1
code = models.CharField(max_length=4) # Erm, no index on this column ..... 
name = models.CharField(max_length=64) # Erm, no index on this column ..... 

Vous pouvez passer l'argument de mot-clé unique = True et de la valeur pour les deux ci-dessus.

geog_region_id = models.ForeignKey(GeogRegion) # Is this correct ? (how about ref integrity constraints ? 
ccy_id = models.ForeignKey(Currency) # Is this correct? 

Les lignes ci-dessus sont exactes si GeogRegion et Currency sont définis avant que ce modèle. Sinon, mettez des guillemets autour des noms de modèles. Par exemple models.ForeignKey("GeogRegion"). Voir documentation.

flag_image_path = models.CharField(max_length=64) # How to set default on this col? 

Facile. Utilisez l'argument et la valeur du mot-clé default = "/foo/bar".

created_at = models.DateTimeField() # Will this default to now() ? 

Pas automatiquement. Vous pouvez faire default = datetime.now (rappelez-vous d'abord from datetime import datetime). Alternativement, vous pouvez spécifier auto_now_add = True.

# Don't know how to specify indexes and unique indexes .... 

Jetez un coup d'œil à unique_together.

Vous verrez que le document auquel j'ai lié est le même que celui indiqué par d'autres personnes. Je vous encourage fortement à lire les documents et à travailler à travers le tutorial.

Questions connexes