Django add inlines to CreateView - django

I have the following admin.py
class AInlineAdmin(admin.TabularInline):
model = A
class BAdmin(admin.ModelAdmin):
fields = ['name']
list_display = ['name']
ordering = ['name']
inlines = [AInlineAdmin]
admin.site.register(B, BAdmin)
class AAdmin(admin.ModelAdmin):
fields = ['identifier']
list_display = ['identifier']
ordering = ['identifier']
admin.site.register(A, AAdmin)
And the following models.py:
class B(models.Model):
name = models.CharField(max_length=100)
def get_A(self):
return "\n".join([i.identifier for i in self.a.all()])
def __unicode__(self):
return self.name
class A(models.Model):
identifier = models.CharField(max_length=200, blank=False, default="")
c = models.ForeignKey(B, related_name='a', default=0)
def __unicode__(self):
return self.identifier
And the following views.py:
class BCreate(CreateView):
model = B
fields = ['name', 'a']
But it is not working with 'a' inside "fields = ['name', 'a']", as 'a' is not found.
How can I get inlines into the view so I could edit/delete/create A inside B view?

The CreateView does not support this. You could use django-extra-views, which comes with CreateWithInlinesView and UpdateWithInlinesView views.

Related

Adding fields from a many-to-many relationship to a Django Admin Inline

I am trying to set up a project where I have user, questions for the users, and then the answers that the users give. Here are my models.
class User(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField()
def __str__(self):
return self.name
class Question(models.Model):
question = models.TextField()
def __str__(self):
return self.question
class Answer(models.Model):
answer = models.TextField()
user = models.ManyToManyField(User)
question = models.ManyToManyField(Question)
def __str__(self):
return self.answer
Then in the admin I would like to be able to click on a user and see their answers so I set my admin up like so.
class AnswerInline(admin.TabularInline):
model = Answer.user.through
class UserAdmin(admin.ModelAdmin):
list_display = ('name', 'email')
inlines = [AnswerInline]
class QuestionAdmin(admin.ModelAdmin):
list_display = ('question',)
class AnswerAdmin(admin.ModelAdmin):
list_display = ('answer', )
fields = ('question', 'answer',)
admin.site.register(User, UserAdmin)
admin.site.register(Question, QuestionAdmin)
admin.site.register(Answer, AnswerAdmin)
However, when viewing users it only shows their answer. It doesn't show the question that answer is associated with. How do I add this information to the admin page in a way that makes sense. Preferably with the question first and then the answer to that question to the right of it.
Update
I added this to the admin inline, however it shows up blank. So I still need it to show the actual string that is the "question"
class AnswerInline(admin.TabularInline):
model = Answer.user.through
fields = ('question', 'answer')
readonly_fields = ('question',)
extra = 0
def question(self, obj):
q = self.question.question
return q
So it turns out I set up the models incorrectly. Here is how they should look.
from django.db import models
class User(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField()
def __str__(self):
return self.name
class Question(models.Model):
question = models.TextField(default=None)
people = models.ManyToManyField(User, through='Answer')
def __str__(self):
return self.question
class Answer(models.Model):
answer = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
question = models.ForeignKey(Question, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.answer
and then here is the admin that works.
class AnswerInline(admin.TabularInline):
model = Answer
fields = ('question', 'answer')
readonly_fields = ('question', 'answer')
extra = 0
class UserAdmin(admin.ModelAdmin):
list_display = ('name', 'email')
inlines = [AnswerInline]
class QuestionAdmin(admin.ModelAdmin):
list_display = ('question',)
class AnswerAdmin(admin.ModelAdmin):
list_display = ('answer',)
fields = ('question', 'answer', 'user')

How i can serialized data to json with drf serializer

I have data models like:
from django.db import models
class Student(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
def __str__(self):
return self.first_name + ' ' + self.last_name
class Course(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
start_date = models.DateField(null=True)
end_date = models.DateField(null=True)
def __str__(self):
return self.name
class CourseParticipant(models.Model):
course = models.ForeignKey(Course, related_name='courses', on_delete=None)
student = models.ForeignKey(Student, related_name='students', on_delete=None)
completed = models.BooleanField(null=True, default=False)
def __str__(self):
return self.course
I have some serializer like:
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ('name', 'end_date', 'start_date')
I need return data in json like:
{
"courses": [
{
"name": "Math",
"end_date": "2019-06-26",
"start_date": "2019-06-26",
"participant_students_count: 10
}
]
}
How I can get "participant_students_count" and return its data in json with other fields.
Thanks for help!
You can use SerializerMethodField of DRF serializer field. Also, see about how to follow Backward access of Foreign key relationship.
from rest_framework import serializers
class CourseSerializer(serializers.ModelSerializer):
participant_students_count = serializers.SerializerMethodField()
class Meta:
model = Course
fields = ('name', 'end_date', 'start_date', 'participant_students_count')
def get_participant_students_count(self, obj):
return obj.courseparticipant_set.count()
class CourseSerializer(serializers.ModelSerializer):
participant_students_count = serializers.SerializerMethodField()
def get_participant_students_count(self, obj):
return CourseParticipant.objects.filter(course=obj).count()
class Meta:
model = Course
fields = ('name', 'end_date', 'start_date', 'participant_students_count')

Serializer Error When Using Rest Framework to Serialize Nested Objects from Model

I have seen some related posts, but I am not sure what I need to do.
I have set up a view to serialize my test model which has nested models. I have set up the serializers, but I get the error "Got AttributeError when attempting to get a value for field Question on serializer TestSerializer.\nThe serializer field might be named incorrectly".
My Serializers:
class AnswerSerializer(serializers.ModelSerializer):
class Meta:
model = Answer
fields = ('id', 'number', 'text', 'iscorrect')
class QuestionSerializer(serializers.ModelSerializer):
answer = AnswerSerializer()
class Meta:
model = Question
fields = ('id', 'number', 'text', 'answer')
related_object = 'answer'
class TestSerializer(serializers.ModelSerializer):
question = QuestionSerializer()
class Meta:
model = Test
fields = ('id', 'name', 'question')
related_object = 'question'
My Models:
class Test(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
name = models.CharField(max_length=255,default='',blank=False)
datecreated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Question(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE)
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
def __str__(self):
return self.text
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
iscorrect = models.BooleanField(default=False)
def __str__(self):
return self.text
The call from the view:
serializer = TestSerializer(test, many=True)
You have set the related_name in the foreign key other wise default related name is {model_name}_set.
class Question(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE, related_name='questions')
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
def __str__(self):
return self.text
in serializer you can access that fields
class TestSerializer(serializers.ModelSerializer):
questions = QuestionSerializer(many=True)
class Meta:
model = Test
fields = ('id', 'name', 'question')
related_object = 'question'

DetailSerializer to have listserializer property

I want to add json data from the listserializer to the DetailSerializer class. The serializer looks something like this:
serializer.py
class ListSerializer(serializers.ModelSerializer):
class Meta:
model = Fastest_laps
fields = '__all__'
class DetailSerializer(serializers.ModelSerializer):
listserializer = ListSerializer( read_only=True, many=True)
class Meta:
model = Driver
fields =
('place_of_birth','driver','listserializer','picture')
But i dont really see the data once i view it, i only see the detailserializer data( Driver model)
class Fastest_laps(models.Model):
driver_name = models.CharField(max_length=25, null=True)
grand_prix = models.CharField(max_length=15, blank=True)
car_model = models.CharField(max_length=50)
time_taken = models.CharField(blank=True, max_length=8)
def __str__(self):
return self.driver_name
class Driver(models.Model):
place_of_birth = models.CharField(max_length=25)
driver = models.ForeignKey(Fastest_laps,
db_column='driver_name')
picture = models.ImageField(blank=True, null=True)
def __str__(self):
return str(self.driver)
api.py
class FastLapsSet(ModelViewSet):
queryset = Fastest_laps.objects.all()
serializer_class = ListSerializer
class DriverSet(ModelViewSet):
queryset = Driver.objects.all()
serializer_class = DetailSerializer
you should rename your property as model name field:
class DetailSerializer(serializers.ModelSerializer):
driver = ListSerializer(read_only=True)
# ^^^
class Meta:
model = Driver
fields =
('place_of_birth','driver','driver','picture')
or add the source attribute:
class DetailSerializer(serializers.ModelSerializer):
listserializer = ListSerializer(source='driver', read_only=True)
#^^^^
class Meta:
model = Driver
fields =
('place_of_birth','driver','listserializer','picture')

django admin nested inlines with mptt children

I'm trying to figure out if it's possible to create a ModelAdmin with multiple nested inlines like:
Contract
Mainproduct
Subproduct1
Subproduct2
SubSubproduct
And I'm also trying to solve the models with mptt.
My models are looking like this:
class Contract(models.Model):
contractnumber = models.CharField(max_length=25)
field2 = models.CharField(max_length=25)
field3 = models.CharField(max_length=25)
field4 = models.CharField(max_length=25)
def __str__(self):
return self.field1
class Meta:
verbose_name = 'Contract'
verbose_name_plural = 'Contracts'
class Mainproduct(MPTTModel):
pr_c_contractnumber = models.ForeignKey(Contract)
pr_name = models.Charfield(max_length=50)
productdetails = models.Textfield(max_length=5000)
pr_sernr = models.CharField(max_length=50)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True,
on_delete=models.SET_NULL)
def __str__(self):
return self.pr_c_contractnumber, self.pr_name
class MPTTMeta:
order_insertation_by = ['pr_sernr']
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
My admin.py file is looking like this:
class ProductModelInlineForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Product.objects.all())
class ProductModelInline(admin.TabularInline):
model = Product
form = ProductModelInlineForm
extra = 1
class ProductAdmin(admin.ModelAdmin):
inlines = [ProductModelInline, ]
class ProductInline(admin.TabularInline):
model = Product
extra = 1
class ContractAdmin(admin.ModelAdmin):
inlines = [ProductInline, ]
Is there a way to create these nested inlines? Am I missing something important?
Just use MPTTModelAdmin and it will do it automatically:
from mptt.admin import MPTTModelAdmin
admin.site.register(Mainproduct, MPTTModelAdmin)