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
Related
If I sound confused, it's because I am.
I'm unfamiliar with the django rest framework and I'm attempting to create a relatively simple Recipe-Managing app that allows you to automatically create your shopping list.
Motivations :
I know that DRF might not be needed and I could just use django, but the point of this app is to learn how to use the DRF.
The goal is to create a back with DRF and do some fancy shenanigans with a front framework afterward.
Problem:
I have a Recipe model which contains a ManyToMany field to Ingredient through RecipeIngredient. And I am a bit confused on how I should approach the RecipeSerializer.
So far it looks like that :
class RecipeSerializer(serializers.ModelSerializer):
class Meta:
model = Recipe
fields = ('id','name','ingredients','tags','prep_time','cook_time', 'servings', 'instructions')
But I feel like whenever I will want to create a Recipe, I'll have to fire a post request to create the Ingredients (if they do not exist yet), one to create the Instructions, one to create the Recipe and one to create the RecipeIngredients.
Question :
Is there a way to make one request containing the recipe and all sub fields (ingredient, recipeingredient, instruction) and to create all the entities ?
That would be handled by the create function of the RecipeSerializer I suppose.
Model:
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
class Ingredient(models.Model):
name = models.CharField(max_length=100, unique=True)
class Recipe(models.Model):
name = models.CharField(max_length=100)
ingredients = models.ManyToManyField(Ingredient,through='RecipeIngredient')
tags = models.ManyToManyField(Tag, related_name='recipes')
prep_time = models.PositiveIntegerField()
cook_time = models.PositiveIntegerField()
servings = models.PositiveIntegerField()
class Instruction(models.Model):
number = models.PositiveIntegerField()
text = models.TextField()
recipe = models.ForeignKey(Recipe, related_name='instructions', on_delete = models.CASCADE)
class RecipeIngredient(models.Model):
ingredient = models.ForeignKey(Ingredient, on_delete = models.CASCADE)
recipe = models.ForeignKey(Recipe, on_delete = models.CASCADE)
quantity = models.PositiveIntegerField()
unit = models.CharField(max_length=30, null= False, blank=True)
Serializers:
class TagSerializer(serializers.ModelSerializer):
recipes = serializers.PrimaryKeyRelatedField(queryset = Recipe.objects.all(), many = True)
class Meta:
model = Tag
fields = ('id','name', 'recipes')
class InstructionSerializer(serializers.ModelSerializer):
class Meta:
model = Instruction
fields = ('id','number','text','recipe')
class IngredientSerializer(serializers.ModelSerializer):
class Meta:
model = Ingredient
fields = ('id','name')
class RecipeIngredientSerializer(serializers.ModelSerializer):
class Meta:
model = RecipeIngredient
fields = ('id','ingredient','recipe','quantity','unit')
class RecipeSerializer(serializers.ModelSerializer):
class Meta:
model = Recipe
fields = ('id','name','ingredients','tags','prep_time','cook_time', 'servings', 'instructions')
You can use nested serializers, You can change the RecipeSerializer as follows
class IngredientSerializer(serializers.ModelSerializer):
class Meta:
model = Ingredient
fields = '__all__'
class RecipeSerializer(serializers.ModelSerializer):
ingredients = IngredientSerializer(many=True)
class Meta:
model = Recipe
fields = ('id','name','ingredients','tags','prep_time','cook_time', 'servings', 'instructions')
models.py
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(decimal_places=5,max_digits= 1500)
summary = models.TextField()
featured = models.BooleanField()
def __str__(self):
return self.title
# return f'product title:{self.title}-product price:{self.price}'workok
class Meta:
ordering = ('-price',)
class Opinion(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField(max_length=20)
body = models.TextField()
opinion_date = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='opinion_set')
def __str__(self):
return f'({self.name}) add opinion about ({self.product})'
forms.py:
from django.forms import ModelForm
from .models import Product #space after from keyword
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
invalid in code line :
fields = ['name','email','body','product'] #---- NOT WORK !!!
, but if i change above code to :
fields = "__all__" # ----it is WORKing ok without any problem !!
question : what is the error? I am not need all the fields in the Product model (like active boolean field), I need only 'name','email','body','product' fields .
According to the error and the code you provided the main problem is that you made a mistake in chosing model in serializer:
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
Serializer name is OpinionModelForm and listed fields belong to Opinion so I guess you actually wanted to serialize Opinion and no Product as you defined at this line:
model = Product
Simply change it to:
model = Opinion
How to update more than one object of different model types from one end point. I tried it many ways but i still fails.I tried through nested serializer and create method, but it is still not working
class Student(models.Model):
name = models.CharField(max_length=300)
sex = models.CharField(choices=SEX_CHOICES,max_length=255,
null=True)
Category = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
class Registration(models.Model):
registration_no = models.CharField(max_length=255,
unique=True)
student = models.OneToOneField(Student,
on_delete= models.CASCADE, related_name='registrations')
def __str__(self):
return self.registration_no
class RegistrationSerializer(serializers.ModelSerializer):
class Meta:
model = Registration
fields = '__all__'
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = '__all__'
class StudentDataMigrateSerializer(serializers.Serializer):
student = StudentSerializer()
registation = RegistrationSerializer()
In Django Rest Framework by default the nested serializers are read only. To have a writable nested serializer you need to implement create() and/or update() methods.
Take a look at the official documentation https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers
class StudentDataMigrateSerializer(serializers.Serializer):
student = StudentSerializer()
registation = RegistrationSerializer()
def create(self, validated_data):
# save the data
As stated in the title how does manytomanyfield with through appear in the admin site?
class SchoolClass(models.Model):
id = models.AutoField(primary_key = True)
class_name = models.TextField()
level = models.IntegerField()
taught_by = models.ManyToManyField(User,related_name="teacher_teaching",through='TeachSubject')
attended_by = models.ManyToManyField(User,related_name='student_attending')
def __unicode__(self):
return self.class_name
class Meta:
db_table = 'classes'
class TeachSubject(models.Model):
teacher = models.ForeignKey(User)
class_id = models.ForeignKey(SchoolClass)
subject = models.ForeignKey(Subject)
In the admin site, for the model SchoolClass, I have a field for attending students, but not the teachers.
You should use InlineModelAdmin. Docs.
class TeachSubjectInline(admin.TabularInline):
model = TeachSubject
extra = 2 # how many rows to show
class SchoolClassAdmin(admin.ModelAdmin):
inlines = (TeachSubjectInline,)
admin.site.register(SchoolClass, SchoolClassAdmin)
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...