Is it possible to create a verbose name for the actual Class model?
class User(models.Model):
fname = models.CharField(max_length=50, verbose_name = 'first name')
So in the admin panel it will be referenced by its verbose name and not 'user' ?
class User(models.Model):
fname = models.CharField(max_length=50, verbose_name = 'first name')
class Meta:
verbose_name = "users"
Source: https://docs.djangoproject.com/en/2.1/topics/db/models/#meta-options
verbose_name and verbose_name_plural both the properties of Meta class are very important to modify the default behaviour of Django to display the name of our models on Admin interface.
You can change the display of your model names using on Admin Interface using verbose_name and verbose_name_plural properties and model fields names using keyword argument verbose_name.
Please find the below 2 examples.
Country model:
class Country(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, help_text="Your country", verbose_name="name")
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"Country {str(self.id)} - {self.name}"
class Meta:
verbose_name = "Country"
verbose_name_plural = "Countries"
If you will not specify verbose_name_plural then Django will take it as Countrys which does not look good as we want it as Countries.
This better fits in the following type of Model.
Gender model:
class Gender(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, help_text="Gender", verbose_name = "name")
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"Gender {str(self.id)} - {self.name}"
class Meta:
verbose_name = "Gender"
You could add a "verbose_name_plural" to the "Meta" class too.
To alter admin model without polluting the model itself, you can utilize a proxy admin model, like this:
# admin.py
from . import models
class Users(models.User):
class Meta:
proxy = True
class UsersAdmin(admin.ModelAdmin):
...
admin.site.register(Users, UsersAdmin)
ConfigAbility._meta.verbose_name = 'config ability'
ConfigAbility._meta.verbose_name_plural = 'config ability'
I did explore this, but don't know whether it's the thing you need. I put those codes in class ConfigAbilityAdmin in Admin.py. Then, the result:
enter image description here
With this approach, you don't need to config Meta method in model class, especially when model class's code is generated from inspectdb...
Related
I have following models:
from django.db import models
class City(models.Model):
name = models.CharField(max_length=30)
last_update = models.DateTimeField(null=True)
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
Now using Django Rest Framework, I would like to create serializer that will return City details along with the list of all BusStops in the city - but I want the list to be only strings with BusStop names, like this:
{
"id": 1
"name": "City"
"last_update": "2019-09-19T22:13:54.851363Z"
"bus_stops": [
"stop1",
"stop2",
"stop3"
]
}
What I've tried so far is following serializers:
from rest_framework import serializers
class BusStopSerializer(serializers.ModelSerializer):
class Meta:
model = BusStop
fields = ('name', )
class CityDetailsSerializer(serializers.ModelSerializer):
busstop_set = BusStopSerializer(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'busstop_set')
But this creates list of objects with 'name' in them. So, how can I create a list with only BusStop names (as strings) in it?
Instead of the extra BusStopSerializer you could use a StringRelatedField:
# models.py
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
def __str__(self):
return self.name
# serializers.py
class CityDetailsSerializer(serializers.ModelSerializer):
bus_stops = StringRelatedField(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'bus_stops')
StringRelatedField, as recommended by wfehr, will only work as long as the __str__ method of BusStop only returns the name. An alternative is to use SlugRelatedField which allows you to specify a particular field from the related model, and has no dependency on __str__.
bus_stops = SlugRelatedField(many=True, slug_field='name')
I have those extremely simple models:
class Activity(BaseModel):
name = models.CharField(max_length=200, blank=True, null=True)
class Person(BaseModel):
activities = models.ManyToManyField('Activity', related_name='persons')
In the admin.py I've made an inline for this and it works, like this:
class PersonActivitiesInlineAdmin(admin.StackedInline):
model = Profession.persons.through
fk_name = 'person'
class PersonAdmin(admin.ModelAdmin):
inlines = (PersonActivitiesInlineAdmin, )
My problem is that the string describing the inline, in the admin interface, is like
Profession: Person_activities object (831)
Profession: Person_activities object (832)
Profession: Person_activities object (835)
Profession: Person_activities object (838)
So how to customize the "description" of the manytomany inline in the admin panel?
A possible solution is to explicitly create the join model for the many-to-many relationship of Person and Activity by using through and add description to it:
class Activity(BaseModel):
name = models.CharField(max_length=200, blank=True, null=True)
class Person(BaseModel):
activities = models.ManyToManyField(
Activity,
related_name='persons',
through='PersonActivity' # Use PersonActivity for join model
)
class PersonActivity(BaseModel):
description = models.CharField(max_length=255) # Your custom description field
activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
def __str__(self):
# The admin automatically renders the string representation of the model
# e.g. Person_activities object (838)
# Thus you can return your custom description in order to display it
return self.description
I am trying to make an app where users will login to their profile and can add songs to their favorite list. I am defining a M2M relationship for this.
My question is how to say combination of (song, singer) is unique?
I searched and found that it may be possible through unique_together. Is this the correct way of setting this?
models.py:
from django.contrib.auth.models import User
class Singer(models.Model):
name = models.CharField(max_length=500, unique=True)
def __str__(self):
return self.name
class Song(models.Model):
id = models.AutoField(primary_key=False)
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
Class Meta:
unique_together = (singer, id)
def __str__(self):
return self.name
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
songs = models.ManyToManyField(Song, related_name='profile')
def __str__(self):
return self.user.username
Please feel free to correct my models.py, if you think the relationship is not correct.
Thanks,
I would use a default primary key (auto field), and use the meta class property, unique_together
class Song(models.Model):
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
class Meta:
unique_together = (("singer", "name"),)
It would act as a "surrogate" primary key column.
You don't specify id in your model song. I would also recommend to use slug field of django and specify unique on the same. Just in case you have two singers with the same name. Then the second or more you put like abc, abc-1, abc-2, in which case you don't have to change the name and unique_together clause works just fine.
class Song(models.Model):
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
class Meta:
unique_together = (("singer", "name"),)
def __str__(self):
return self.name
I can't seem to figure out how to use this thing:
I have these 3 models:
Recipe has an ingredient_list that is comprised of the IngredientType through the Ingredient model.
Here they are (simplified)
class Recipe(models.Model):
name = models.CharField(max_length=200)
ingredient_list = models.ManyToManyField(IngredientType, through='Ingredient')
difficulty =models.CharField(max_length=1,choices=DISH_DIFICULTY,
default=INTERMEDIATE)
cuisine = models.ManyToManyField(Cuisine, related_name='+', null=True,
blank = True)
class Ingredient(models.Model):
ingredient_type = models.ForeignKey(IngredientType)
class Meta:
app_label = 'vcb'
verbose_name = _('Ingredient')
verbose_name_plural = _('Ingredients')
def __unicode__(self):
return ''
class IngredientType(models.Model):
name = models.CharField(max_length=200)
plural_name = models.CharField(max_length=200)
class Meta:
app_label = 'vcb'
verbose_name = _('Ingredient Type')
verbose_name_plural = _('Ingredient Types')
def __unicode__(self):
return self.name
Now in my recipe admin I have:
class IngredientInline(admin.TabularInline):
model = Ingredient
extra = 0
class RecipeAdmin(admin.ModelAdmin):
inlines = [IngredientInline]
My problem is that all the fields, including the Ingredient tab in my admin form are not being translated.
I've specified translations, in the LC_MESSAGES->django.po, to all IngredientTypes objects and all other fields, but when opening the admin api or ingredient list, they're all in English.
(I've compiled the translations and synced them).
I've tried the django-modeltranslation approach, only to find that it can't work with a manyTomany Field.
Is there a form.py I should add? I've been using django default by now, but if that's a lead, do tell.
Help is much appreciated,
Nitzan
Django ContentTypes provides a GenericInlineFormSet, however the documentation does not explain how to use it, except for this test, which doesn't really explain it in a way I understand.
Please can you help me understand it?
Let's say I have the following classes
class Dog(models.Model):
name = models.CharField(max_length=64)
breed = models.CharField(blank=True, max_length=64)
class Meta:
verbose_name = 'Dog'
class Fish(models.Model):
name = models.CharField(max_length=64)
habitat = models.CharField(blank=True, max_length=64)
class Meta:
verbose_name = 'Fish'
class Pet(models.Model):
content_type = models.ForeignKey(
ContentType,
limit_choices_to={'model__in':('dog', 'fish')},
verbose_name='Species'
)
object_id = models.CharField(max_length=64, verbose_name='Animal')
object = generic.GenericForeignKey('content_type', 'object_id')
owner = models.ForeignKey(Owner)
class Meta:
unique_together = [("content_type", "object_id")]
What does the view look like to display a form for a Pet?
GenericInlineFormSet works just like a standard inline formset, except that it uses generic relations rather than standard foreign keys.