The use of model field "verbose name" - python

If I have a web app that use only one language and it is not English, is that correct to use model field verbose_name attribute for the field description (that will be printed in form)? I dont use the translation modules.

Verbose Field Names are optional. They are used if you want to make your model attribute more readable, there is no need to define verbose name if your field attribute is easily understandable. If not defined, django automatically creates it using field's attribute name.
Ex : student_name = models.CharField(max_length=30)
In this example, it is understood that we are going to store Student's name, so no need to define verbose explicitly.
Ex : name = models.CharField(max_length=30)
In this example, one may be confused what to store - name of student or Teacher. So, we can define a verbose name.
name = models.CharField("student name",max_length=30)

Related

(Django 1.10) referring to properties of an object referred to by ForeignKey

In my app each object Kurs needs to have a field 'prowadzacy' specifying the user to which the given Kurs belongs. Therefore, my models.py has the following:
class Kurs(models.Model):
prowadzacy = models.ForeignKey(User)
I also need to know the first name of the user in possession of the given Kurs. In shell, the following works:
>>> k=Kurs.objects.get(id=1)
>>> k
<Kurs: Wprowadzenie do epi 2>
>>> k.prowadzacy
<User: leszekwronski>
>>> k.prowadzacy.first_name
u'Leszek'
Eventually I need to have a field in my Kurs object containing an outcome of a procedure transforming the possessor's first and last names.
As a first step, I want to add a field containing just the first name. However, when I modify my models.py to contain the following:
class Kurs(models.Model):
prowadzacy = models.ForeignKey(User)
imie = prowadzacy.first_name
then I get the following error:
AttributeError: 'ForeignKey' object has no attribute 'first_name'
I tried using 'self.prowadzacy.first_name' instead of just 'prowadzacy.first_name', but to no avail:
NameError: name 'self' is not defined
What am I doing wrong? After reading this I suspect that I cannot refer to the name of a field in a model until the definition of that particular model is finished. However, 1) I'm not sure and would be grateful for a decisive 'yes' or 'no' and 2) if that's the case, how I can refer to "the first name of the particular user which is the value of a different field in the model I am defining now"?
A "procedure" means a method. If you want your Kurs model to be able to display the full user name, write a method to do it.
class Kurs(models.Model):
...
def full_user_name(self):
return u'{} {}'.format(self.prowadzacy.first_name, self.prowadzacy.last_name)

ForeignKey vs CharField

I have an idea for data model in django and I was wondering if someone can point out pros and cons for these two setups.
Setup 1: This would be an obvious one. Using CharFields for each field of each object
class Person(models.Model):
name = models.CharField(max_length=255)
surname = models.CharField(max_length=255)
city = models.CharField(max_length=255)
Setup 2: This is the one I am thinking about. Using a ForeignKey to Objects that contain the values that current Object should have.
class Person(models.Model):
name = models.ForeignKey('Name')
surname = models.ForeignKey('Surname')
city = models.ForeignKey('City')
class Chars(models.Model):
value = models.CharField(max_length=255)
def __str__(self):
return self.value
class Meta:
abstract = True
class Name(Chars):pass
class Surname(Chars):pass
class City(Chars):pass
So in setup 1, I would create an Object with:
Person.objects.create(name='Name', surname='Surname', city='City')
and each object would have it's own data. In setup 2, I would have to do this:
_name = Name.objects.get_or_create(value='Name')[0]
_surname = Surname.objects.get_or_create(value='Surname')[0]
_city = City.objects.get_or_create(value='City')[0]
Person.objects.create(name=_name, surname=_surname, city=_city)
Question: Main purpose for this would be to reuse existing values for multiple objects, but is this something worth doing, when you take into consideration that you need multiple hits on the database to create an Object?
Choosing the correct design pattern for your application is a very wide area which is influenced by many factors that are even possibly out of scope in a Stack Overflow question. So in a sense your question could be a bit subjective and too broad.
Nevertheless, I would say that assigning a separate model (class) for first name, another separate for last name etc. is an overkill. You might essentially end up overengineering your app.
The main reasoning behind the above recommendation is that you probably do not want to treat a name as a separate entity and possibly attach additional properties to it. Unless you really would need such a feature, a name is usually a plain string that some users happen to have identical.
It doesn't make any good to keep name and surname as separate object/model/db table. In your setup, if you don't set name and surname as unique, then it doesn't make any sense to put them in separate model. Even worse, it will incur additional DB work and decrease performance. Now, if you set them as unique, then you have to work over the situation when, e.g. some user changes his name and by default it would be changed for all users with that name.
On the other hand, city - there're not that many cities and it's a good idea to keep it as separate object and refer to it via foreign key from user. This will save disk space, allow to easily get all users from same city. Even better, you can prepopulate cities DB and provide autocompletion fro users entering there city. Though for performance you might still want to keep city as a string on the user model.
Also, to mention 'gender' field, since there're not many possible choices for this data, it's worth to use enumeration in your code and store a value in DB, i.e. use choices instead of ForeignKey to a separate DB table.

Python constants

I am in the middle of a development in Django and we got some doubts about if we should use or not constants in the project. Exactly the situation is to use constants everywhere or not (we know constants in Django are not really read-only).
There are 2 scenarios and I would like to get your opinion about which one is better for you and why:
Scenario 1 (using constants)
constants.py
class CONST():
def NAME(): return "name"
def SURNAME(): return "surname"
def ZIPCODE(): return "zipcode"
def CITY(): return "city"
def CREATED(): return "created"
admin.py
from constants import CONST
class RegisterAdmin(admin.ModelAdmin):
list_display = (CONST.NAME(),CONST.SURNAME(),CONS.ZIPCODE())
list_filter = [CONST.ZIPCODE(),CONST.CITY()]
search_fields = [CONST.NAME(), CONST.SURNAME()]
date_hierarchy = CONST.CREATED()
models.py
from constants import CONST
class Register(models.Model):
name = models.CharField(CONST.NAME(), max_length=25)
surname = models.CharField(CONST.SURNAME(), max_length=25)
zipcode = models.IntegerField(CONST.ZIPCODE())
city = models.CharField(CONST.CITY(),max_length=20)
... and any view etc where you use text will be using contants ...
Scenario 2 (without constants)
admin.py
class RegisterAdmin(admin.ModelAdmin):
list_display = ("name","surname","zipcode")
list_filter = ["zipcode","city"]
search_fields = ["name","surname"]
models.py
class Register(models.Model):
name = models.CharField("name", max_length=25)
surname = models.CharField("surname", max_length=25)
zipcode = models.IntegerField("zipcode")
city = models.CharField("city",max_length=20)
I like the most the second scenario (I have been programming python from 2004), for me it looks more efficient, clear and easy to understand. The first scenario (proposed from Java/PHP programmers that now writes Python code) has the advantage that it helps the developer to detect that it made a mistake writing the "constant" so it is easier to detect errors and also it makes easier and quicker "massive changes" on this kind of texts without refactorizing the source code.
I would like to know which source code you would write or use and why.
Thank you,
Scenario 1 is awful. Unfortunately I know all too well the problems of working with Java/PHP developers who are learning python.
Perhaps you can compromise with those guys by proposing the use of python enums to address their concern. These are built-in in python 3.4+, and have been backported as far back as 2.4.
from enum import Enum
class Constant(Enum):
name = "name"
surname = "surname"
zipcode = "zipcode"
city = "city"
created = "created"
Now you can change the "values", say for example changing zipcode to be "potato" in the enum definition, whilst still using the name Constant.zipcode.value everywhere else in source code.
Scenario 1 doesn't make sense. You're using the constants to specify the verbose_name of the fields, and you're using them in the list_display option. The list_display option takes a list of fieldnames and NOT the verbose_name of the fields.
So you don't need constants at all for this. The field names are your "constants".
And IF you would need some "constants" in some case, you shouldn't use methods, just use properties, and just use normal class/attribute name conventions (so no uppercases):
class SomeConstants():
name = "name"
surname = "surname"
zipcode = "zipcode"
city = "city"
created = "created"
The Java/PHP guys might say something like "Yeah but what if one of the constants needs to be generated? Then you need a method!". Well, sure, so you make it a property:
class SomeConstants():
#property
def full_name(self):
return "{} {}".format(self.name, self.surname)
Because of the #property line above the method, it will execute and return the result of this method if you call SomeConstants().full_name.
Use of constants is sometimes good, but not here.
One, the first argument of a field is its verbose name, if it's missing then the name of the field is used by default. So using the same constant for its verbose name as for the field name is exactly the scenario in which the verbose name is completely unnecessary.
Just do
name = CharField(max_length=25)
or
name = CharField("A beautiful description for a name field", max_length=25)
but putting "name" there is completely redundant and thus wrong. Don't repeat yourself.
Second, your constant is actually used for two different things that you don't want to change at the same time: you use the same constant for the attribute name in admin.py, but for verbose name in models.py. They aren't going to stay the same thing.
Third, using constants is only really helpful if the value might change one day, or if it's not immediately obvious what it may mean, for e.g. PI=3.14.
But NAME = "name" does not make anything more obvious, and if it ever changes to NAME = "description" it immediately becomes actively misleading. You'd probably want to change the name of the constant in that case as well, won't you? Why did you ever use a constant then?
And it means that changing something in const.py changes the database structure that Django expects. Some day a developer is going to trip over that; keep field names in models.py.
Finally, at every place where you use the models, you need the actual field anyway. A Register instance is simply a class instance, after all, and you'll probably want to use fields like register.name anywhere. You don't put the names of attributes of other classes in constants, do you?
Just use the string.
What about something more straight-forward like:
constants.py
NAME = "name"
SURNAME = "surname"
admin.py
import constants
class RegisterAdmin(admin.ModelAdmin):
list_display = (constants.NAME, constants.SURNAME,constants.ZIPCODE)
This provides a unique place for the values in contrast to repeating them as in Scenario 2 and thus I would prefer it. It seems more clear than Scenario 1 to me. The "encapsulation" is performed by the module name, i.e. by using constants.xxx, so don't from constants import *.
The values here are obviously not constant, but neither are they in Scenario 1.
Everyone is in agreement that its a bad idea, but it could be that your Java friends are trying to implement the equivalent of a Java resource bundle, perhaps because they fondly remember how easy it is to work with .properties files.
This results in the use of keys in place of actual names and then later on the system will retrieve the correct resource from the bundle. This technique is used for translations and localization of applications.
A typical resource key looks like key.trx.hist.term.transfer.completed.success and at runtime the equivalent resource is rendered by the application.
If this is the case, in Python the approach is a bit different:
You start with a base language. This is what you write your code in.
All strings that need to be localized or translated are marked for translation, with the gettext library. For convenience this library provides a shortcut method _() which is used to mark strings for translation.
These strings are then extracted to a message file; which is forwarded to translators. The message file contains the file names where the string is used. Its a plain text file, much like the .properties file.
This message file is then compiled into an optimized format.
Based on the language/locale of the client, the correct translated strings are displayed.
You can read more on how this is implemented in django at the translation documentation.

Is there a "short_description" method for variables in Django?

I have a long variable name in one of my models "xxxx_xxxx_xx_xxxxxxxx" is there an equivilent of:
xxxx_xxxx_xx_xxxxxxxx.short_description = 'xxxx'
for variables or do I have to make a method to display that? I would like to not have to use a method because I want to be able to sort by this variable in the Django admin. Thanks.
Look at the verbose field name option. It allows you use whatever name you like in the admin. There is also the verbose_name_plural for model names that have unusual plural construxions.

converting django ForeignKey to a usable directory name

I'm working on a django app where the user will be able to upload documents of various kinds. The relevant part of my models.py is this:
class Materials(models.Model):
id = models.AutoField(primary_key=True)
id_presentations = models.ForeignKey(Presentations, db_column='id_Presentations', related_name = "materials_id_presentations") # Field name made lowercase.
materialpathname = 'documents/'
materialpathname += str(id_presentations)
document = models.FileField(db_column='Document', upload_to = materialpathname) # Field name made lowercase.
docname = models.CharField(max_length=40, db_column='DocName') # Field name made lowercase.
class Meta:
db_table = u'Materials'
My intention is for it to save the documents associated with a given presentation, in a subdirectory with the id number for that presentation (so if "Very Important Presentation" is on the database with id 3, it should store the associated materials at the location settings.MEDIA_ROOT/documents/3/whateverdocname.txt ).
However, while the above code "works", it creates a subdirectory that, instead of being named "3", is named <django.db.models.fields.related.ForeignKey object at 0x8e358ec>, or that kind of thing. I've tried using "id_presentations.name", "id_presentations.value", etc. but these attributes don't seem to exist. I can't seem to find a place where it gives a way to get at the integer value of the ForeignKey field, so that I can convert it to a string and use it as a subdirectory name.
Any help is greatly appreciated.
As of Django 1.0, the upload_to argument to FileFields can be a callable. If I'm understanding your intentions correctly, something like this should do the trick:
def material_path(instance, filename):
return 'documents/%d' % instance.id_presentations.id
class Materials(models.Model):
id_presentations = models.ForeignKey(Presentations)
document = models.FileField(upload_to=material_path)
docname = models.CharField(max_length=40)
That model has been simplified a little bit, but hopefully it illustrates the solution. If upload_to is a callable, then every time a file is uploaded Django will call the function, passing it two arguments: the instance to which the file was uploaded is attached and its original filename. You can generate the file path you want by pulling the ID of the presentation off of the instance in question.
More info:
http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield
Provided that the "name" property is defined on your Presentation model, if you're working with a specific instance of the model then what you want should work. Like this:
from models import Materials
obj = Materials.objects.get([some criteria here])
name = obj.id_presentation.name
If you wanted to abstract that to a method on your model, you could do this:
class Materials(models.Model):
def id_presentation_name(self):
return self.id_presentation.name
If you want the database id of the object, you can access either object.id or object.pk.
Note: you can always find out what attributes and methods are available on an object in python by calling dir(object).

Categories