Trying to learn stacked inlines in Django. Have a very basic setup
For admin.py
from django.contrib import admin
from .models import Picture, Review
class ReviewInline(admin.StackedInline):
model = Review
save_on_top = True
fields = ["reviewer"]
##admin.register(Picture)
class PictureAdmin(admin.ModelAdmin):
save_on_top = True
fields = ["painter"]
inlines = [ReviewInline,]
admin.site.register(Review)
admin.site.register(Picture, PictureAdmin)
For models.py
from django.db import models
class Picture(models.Model):
painter = models.CharField(("painter"), max_length=255)
def __str__(self):
return self.painter
class Review(models.Model):
picture = models.ForeignKey(Picture, on_delete=models.CASCADE)
reviewer = models.CharField( max_length=255)
extra = 0
def __str__(self):
return self.reviewer
As can be seen there is no "add more item" button. I think this might be a JS issue but am not sure(I do have JS enabled in browser)
Anyone has any idea?
I beleive you have the extra=0 in the wrong class, it should be in the Inline not the Model...
Remove extra=0 from the model
class Review(models.Model):
picture = models.ForeignKey(Picture, on_delete=models.CASCADE)
reviewer = models.CharField( max_length=255)
# extra = 0 <---- remove this
def __str__(self):
return self.reviewer
Add it to the Inline:
class ReviewInline(admin.StackedInline):
model = Review
save_on_top = True
extra = 0
fields = ["reviewer"]
Justification comes from this snippet from this example:
#admin.register(Painter)
class PainterAdmin(admin.ModelAdmin):
save_on_top = True
fields = ["name"]
inlines = [PictureInline]
class ReviewInline(admin.StackedInline):
model = Review
extra = 0
fields = ["reviewer", "comment"]
Edit: Second thought you may also want to get rid of the save_on_top from the inline as well?
Clearing my Google Chrome cache solved it! I got a clue after realizing that the example worked in Microsoft Edge.
Related
I have the model created for complaints. I tried a few methods to help a user create the complaint, but nothing works so I have given up and I just want to understand what to add in the views.py so that I can do that. The system basically has multiple users and I want the users to send in their complaints to the admin panel, so that they can be viewed, edited or deleted as per use on the dashboard. Right now my form does get created but it does not save the complaints in the admin panel.
models.py:
class Complaints(models.Model):
user = models.ForeignKey(User, on_delete= CASCADE, null = True, blank=True)
title = models.CharField(max_length=300)
description = models.TextField(null=True, blank= True)
highpriority = models.BooleanField(default=False)
document = models.FileField(upload_to='static/documents')
def __str__(self):
return self.title
what to add in the views.py? I've tried various things but I don't know what to do to make it work.
this if my views.py but I feel like the entire thing is wrong so I want an entirely new views:
class ComplaintCreate(CreateView):
model = Complaints
form = ComplaintForm
fields = '__all__'
success_url = reverse_lazy('New')
template_name = 'new.html'
I want the final page to look like this:
there is not form attribute in CreateView change form to form_class
class ComplaintCreate(CreateView):
model = Complaints
form_class = ComplaintForm
fields = '__all__'
success_url = reverse_lazy('New')
template_name = 'new.html'
I'm trying to build a filter that corresponds to the has_images method on my Django admin, but I can't because it strictly says that has_images is not a field of the model. I tried setting it up as a property, but it also didn't work.
I thought about defining has_images as a field and really calculating it, based on the changes on the model, but I think that would be not optimal.
What would be a good solution here?
models.py
class Product(models.Model):
name = models.CharField("Name", max_length=255)
def has_images(self):
return self.images.all().count() > 0
has_images.boolean = True
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="images")
file = models.ImageField("Product Image")
admin.py
class ProductImageInline(admin.TabularInline):
model = ProductImage
fields = ('file',)
extra = 1
class ProductAdmin(VersionAdmin):
list_display = ('id', 'name', 'has_images',)
inlines = (ProductImageInline,)
Expected result:
Can you share the contents of the admin.py file?
Or let me explain it as follows. Add a feature called list_filter = ('images') into the ProductAdmin class you created in admin.py. If this feature doesn't work (I'm not sure as I haven't tried it), if you create an Admin Class for ProductImages directly, you can already view the pictures and the corresponding Product on that page.
----------- EDIT ----------------
This is how I solved the problem.
models.py
from django.db import models
class Product(models.Model):
name = models.CharField("Name", max_length=255)
is_image = models.BooleanField(default=False, editable=False)
def save(self, *args, **kwargs):
if self.images.count():
self.is_image = True
else:
self.is_image = False
super(Product, self).save(*args, **kwargs)
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="images")
file = models.ImageField("Product Image")
def save(self, *args, **kwargs):
super(ProductImage, self).save(*args,**kwargs)
self.product.save()
admin.py
from django.contrib import admin
from .models import *
class ProductImageInline(admin.TabularInline):
model = ProductImage
fields = ('file',)
extra = 1
class ProductAdmin(admin.ModelAdmin):
list_display = ('id', 'name',)
list_filter = ('is_image',)
inlines = (ProductImageInline,)
admin.site.register(Product, ProductAdmin)
Here I added an is_image BooleanField field with False by default. Every time the save method of the Product model runs, it checks whether there is an image in the ProductImage to which the Product model is attached. If there is an image in it, is_image is set as True.
In our project, i've been making use of the latest version of django-nested-inlines v0.3.7 with django 1.7
I have the following definition in my django admin to display the inlines
class SpecsGroupedContentInline(NestedStackedInline):
model = SpecificationGroupedContent
extra = 1
fk_name = "specification"
fields = ["field_unit"]
class SpecsContentInline(NestedStackedInline):
model = SpecificationListContent
extra = 1
fk_name = "specification"
fields = ["content"]
class SpecsInline(NestedStackedInline):
model = Specification
inlines = [SpecsContentInline, SpecsGroupedContentInline]
extra = 1
fk_name = "product"
class ProductAdmin(NestedModelAdmin):
inlines = [
SpecsInline
]
list_display = ('name', 'sku')
form = ProductAdminForm
When the page loads, the page looks like this
Initial product page load
It's a bit hard to see but the specs section has a title, an inline for Listed Contents and an inline for Grouped Contents. Afterwards, there's an empty Specs section with an empty title, empty Listed Contents, and empty Grouped Contents.
When I press the "Add another Specification" button at the bottom of the Specification inline to add a new row, the result of the new entry looks like this
New Specification entry image
As you can see, the Grouped Content field "Field Unit" is missing. I'm not sure if my setup is incorrect, but i found this stack overflow entry with a similar setup to mine
Django nested inlines not working?
It is for a different error though but we have a similar inline setup so i was thinking this setup is ok for django-nested-inlines.
Also, I'm sure if it's related but is django-nested-inlines affected if a nested inline model is a foreign key of another model? The SpecificationsGroupedContent model is a foreign key of another model unlike the SpecificationsListContent. I did a quick test where the SpecsInline inlines contained either SpecsGroupedContentInline only or SpecsContentInline only. It was working perfectly when using only SpecsContentInline but the error occurs when using SpecsGroupedContentInline.
For reference, here are the models I'm using with the related model for SpecsGroupedContent
class Product(AuthorStampedModel):
name = models.CharField(max_length=100)
sku = models.CharField(unique=True, max_length=100, verbose_name='SKU')
summary = models.TextField(blank=True, default="")
def __unicode__(self):
return self.return_product_details()
def return_product_details(self):
return '%s: %s' % (self.sku, self.name)
class Specification(models.Model):
product = models.ForeignKey('Product', related_name='specs')
title = models.CharField(max_length=100)
def __unicode__(self):
return self.return_spec_string()
def return_spec_string(self):
return '%s: %s' % (self.product.return_product_details(), self.title)
class SpecificationListContent(models.Model):
specification = models.ForeignKey('Specification', related_name='list_content')
content = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Listed Contents'
def __unicode__(self):
return self.specification.return_spec_string()
class SpecificationGroupedContent(models.Model):
specification = models.ForeignKey('Specification', related_name='group_content')
field_unit = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Grouped Contents'
def __unicode__(self):
return self.specification.return_spec_string()
class SpecificationGroupedContentValue(models.Model):
specification_grouped_content = models.ForeignKey(
'SpecificationGroupedContent',
related_name='group_content_value'
)
value = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Grouped Content Values'
def __unicode__(self):
return self.specification_grouped_content.specification.return_spec_string()
Thanks
Given the following models in models.py:
class Profile(models.Model):
name = models.CharField(max_length=30)
email_address = models.CharField(max_length=30)
password = models.CharField(max_length=30)
preferences = models.OneToOneField("Preferences")
def __unicode__(self):
return u"%s" % self.name
class Preferences(models.Model):
likes_hugging = models.BooleanField(default=False)
despises_men = models.BooleanField(default=False)
Now the following form in forms.py...
class PreferencesModelForm(forms.ModelForm):
class Meta:
model = Profile
fields = ("preferences",)
... produces the following result:
But how do I get the following result instead?
you need to override the default widget. Like this:
from django.forms import ModelForm, Textarea
from myapp.models import Author
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={'cols': 80, 'rows': 20}),
}
You can read the full docs here . The problem is that are you using the PreferencesModelForm correctly? The model should be Preferences. If you really trying to made the form for Profile model with preferencesfield, you can use inline formsets. You can read it here.
You need to use a Radio instead of a checkbox in your case, since you have a OneToOne relation.
Just add to your form:
widgets = {
'preferences': forms.RadioSelect(),
}
PS: this question is from last year, I hope you have solved it :) I came here from google and hope to help people in the same situation.
Having a bit of trouble using multiple inlines within my admin console over 3 models which im playing around with.
Models:
class carManufacturer(models.Model):
name = models.CharField(max_length=200)
country = models.CharField(max_length=200)
description = models.CharField(max_length=1000)
def __unicode__(self):
return self.name
class vehicleModel(models.Model):
carManufacturer = models.ForeignKey(carManufacturer)
model = models.CharField(max_length=200)
def __unicode__(self):
return self.model
class vehicleCode(models.Model):
vehicleModel = models.ForeignKey(vehicleModel)
variantCode = models.CharField(max_length=200)
variantBadge = models.CharField(max_length=200)
manuStart = models.DateTimeField('Manufacture Start Date')
manuFin = models.DateTimeField('Manufacture End Date')
def __unicode__(self):
return self.variantCode
What I'm looking to do is when I add a car Manufacturer I can add car Models via my inline, and when I am editing models, I can edit vehicle codes/variants via another inline.
I have an admin.py file I am using:
from Cars.models import carManufacturer, vehicleModel, vehicleCode
from django.contrib import admin
class modelInline(admin.TabularInline):
model = vehicleModel
extra = 0
class codeInline(admin.TabularInline):
variantCode = vehicleCode
extra = 0
class CarAdmin(admin.ModelAdmin):
fields = ['name', 'description', 'country']
inlines = [modelInline]
class VehicleModelAdmin(admin.ModelAdmin):
fields = ['carManufacturer','model']
#inlines = [codeInline]
admin.site.register(carManufacturer, CarAdmin)
admin.site.register(vehicleModel, VehicleModelAdmin)
As soon as I uncomment my second inline which uses the same method as the first I get the following error:
'model' is a required attribute of 'VehicleModelAdmin.inlines[0]'.
I am struggling to understand what I am doing wrong, especially since I have got the first inline working, any input would be much appreciated
The codeInline doesn't have model field for any TabularInline you do need model field like one above. It should have something like following
class codeInline(admin.TabularInline):
model = vehicleCode
extra = 0