django admin inline components - python

I started learn django and I have question. Here is my models:
from django.db import models
class Color(models.Model):
title = models.CharField(max_length=30)
code = models.CharField(max_length=7)
def __unicode__(self):
return '{0} ({1})'.format(self.title, self.code)
class Image(models.Model):
color = models.ForeignKey(Color)
src = models.ImageField(upload_to='media/img/')
alt = models.CharField(max_length=255)
def __unicode__(self):
return '{0} ({1})'.format(self.alt, self.color.title)
class Manufacturer(models.Model):
title = models.CharField(max_length=255)
image = models.ForeignKey(Image)
def __unicode__(self):
return self.title
I need to have possibility to edit image instance on Manufacturer's page (manufacturer has one image). How can I do it in admin.py
I need something like:
class ImageInline(admin.TabularInline):
model = Image
class ManufacturerAdmin(admin.ModelAdmin):
inlines = [ImageInline]
But I receive
Exception Value:
<class 'catalog.models.Image'> has no ForeignKey to <class
'catalog.models.Manufacturer'>
I need one image for one Manufacturer
And second one:
I am planing to create product model, and one product can have many images. I think I should create many to many relation. So how can I describe Product in admin with many images?
Any ideas?

Exception message tells you everything. You need to add FK relation to Image model:
manufacturer = models.ForeignKey(Manufacturer)
If you need only one image for one manufacturer consider putting it in Manufacturer model. This would be more efficient (less DB queries or "select_related" functions) and easier to manage.
As for Many to many relation between Product and Image - just use ManyToManyField (https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/) in Product model and leave Image model as is.

Related

Storing several informations in one variable in Django Models

class Cities(models.Model):
city_main_image = models.FileField()
city_name = models.CharField(max_length=200)
city_info = models.CharField(max_length=1000)
city_images = models.FileField()
In my models.py I have Cities class and I want to upload several images for this class variable, to be clearly for city_images variable how can I do this? Are there any way to do this or not?
Few notes about your code before answering your question.
1) Stick to singular model names, City rather than Cities.
2) Don't repeat the model name in every field, so you get "main_image",
"name", "info", "images".
3) Use ImageField for images rather than FileField.
4) No need to have 2 fields for main_image and images. You can add an extra field to make the image a main image or not.
Now, to answer your question, you need to read about relations in an SQL database.
To use relations between your models with django's ORM, look at https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey
You have 2 options: ForeignKey or ManyToManyField. Stick with the ForeignKey as you don't need a many to many relation.
So you'll have something like the following:
class City(models.Model):
...
class CityImage(models.Model):
image = models.ImageField(...)
city = models.ForeignKey(City) # you might need to add on_delete parameter depending on your django version.
or
class CityImage(models.Model):
image = models.ImageField(...)
class City(models.Model):
...
images = models.ManyToManyField(CityImage)
class Cities(models.Model):
city_main_image = models.FileField()
city_name = models.CharField(max_length=200)
city_info = models.CharField(max_length=1000)
class CityImages(models.Model):
city_id = models.ForeignKey(Cities)
city_images = models.FileField()
Now each of your city in Cities can have one or more images in another model called CityImages. If we talk in terms of tables then the primary key for a row in table Cities would be associated to one or more rows in table city_images. I will strongly suggest you to go through official introductory tutorial of django. Also I personally find this tutorial very helpful for beginners. Just in case it helps.
One way you could do this is to make a CityImage model, which would allow you to make a ForeignKey to the City model, with a related_name=images for the reverse lookup.
class City(models.Model):
name = models.CharField(max_length=200)
info = models.CharField(max_length=1000)
#property
def main_image(self):
try:
return self.images.get(primary=True)
except CityImage.DoesNotExist:
pass
except CityImage.MultipleObjectsReturned:
# Handle this case, the application should ensure only one is set to `True` at a time...
class CityImage(models.Model):
city = models.ForeignKey(City, related_name='images')
primary = models.BooleanField(default=False)
image = models.FileField()

Django model references from a different model

I'm writing a method in a model and I need to access an attribute from another model.
from django.db import models
class Image(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to = slug_path)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
def slug_path(self):
# Need Article.slug from Article class here for constructing path
pass
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
slug = models.SlugField(max_length=50)
def __str__(self):
return self.headline
I want to write a method in the Image class that will have access to the slug of the Article it is included in via the one to many relation. Is this possible or is there a different way I should be going about this entirely?
Say if only one image can be related to one article, you need to add a field article in the image model which would be foreign key to Article model
article = models.ForeignKey(Article)
Now,
def slug_path(self):
slug = self.article.slug
return slug
Anyway, you can do it in a similar way for many to many fields etc.
Add a relationship to Image corresponding to the Article object, like you did with Article and Reporter.
article = models.ForeignKey(Article, on_delete=models.CASCADE)
Then to get/return the slug:
def slug_path(self):
return self.article.slug

Building a Python Django model with multiple images

I have the following models in Django:
class SpaCenter(models.Model):
name = models.CharField(max_length=50)
street = models.CharField(max_length=200)
house_name = models.CharField(max_length=100)
house_number = models.IntegerField()
city = models.CharField(max_length=50)
country = models.CharField(max_length=50)
region = models.CharField(max_length=50)
class SpaCenterImages(models.Model):
spacenter = models.ForeignKey(SpaCenter)
image = models.ImageField()
primary_image = models.BooleanField()
class SpaCenterWebsites(models.Model):
spacenter = models.ForeignKey(SpaCenter)
website = models.CharField(max_length=300)
PART 1:
I would like:
1) the "SpaCenter" model to have multiple images belonging to it, and 2) One of those images to be selectable as the "primary" image.
Whats the best way to go about building a django model for that? I think I got (1) right...but overall would like to hear some advice on model design.
Basically the same principle as Facebook - 1 profile can have multiple images.
PART 2:
How would one go about scripting the Django admin console for these models in order to allow for multiple images to be uploaded against one profile.
I am quite new to Django, so help is very appreciated. Thank you.
I implemented similar functionality as yours before. To me it's not so clear how to restrict one primary_image for SpaCenter in the model level, but your model design seems to be enough to achieve what you want.
What you can do is to use django formset to make sure there's only one primary exists. Here's a rough idea(not tested):
class SpaCenterImageFormSet(BaseModelFormSet):
def clean(self):
super(SpaCenterImageFormSet, self).clean()
primary_count = 0
for form in self.forms:
if 'primary_image' in form.cleaned_data and \
form.cleaned_data['primary_image']:
primary_count += 1
if self.forms and primary_count == 0:
raise ValidationError("You must have one primary image!")
if primary_count > 1:
raise ValidationError("You cannot have more than one primary image!")
One last thing, don't use plural form in model names, django will add it for you when needed, or you can customize it yourself.
For your part 2 of the question, use normal admin for SpaCenter and Inline for SpaCenterImage https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#inlinemodeladmin-objects

Django one-to-many, add fields dynamically in Admin

I have the following code:
class Item(models.Model):
name = models.CharField(max_length=100)
keywords = models.CharField(max_length=255)
type = models.ForeignKey(Type)
class Meta:
abstract = True
class Variant(models.Model):
test_field = models.CharField(max_length=255)
class Product(Item):
price = models.DecimalField(decimal_places=2, max_digits=8,null=True, blank=True)
brand = models.ForeignKey(Brand)
variant = models.ForeignKey(Variant)
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in Product._meta.fields]
def __unicode__(self):
return self.name
Im using Grappelli.
I want my Product to have multiple Variations. Should I use a manytomanyfield?
I want to be able to add Variants to my Product directly in the Admin. Now I get an empty dropwdown with no variants(because they doesnt exists).
I thought Django did this automatically when u specified a Foreign Key?
How can I get the Variant fields to display directly on my Product page in edit?
I've read someting about inline fields in Admin?
Well, it's the other way around :)
1/ Place the foreign key field in your Variant, not in your Product (what you describe is actually a OneToMany relationship).
2/ Link the Variant to your Product in the relative ProductAdmin in admin.py as an inline (i.e VariantInline).
See the docs for further informations : https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#inlinemodeladmin-objects
Hope this helps !
Regards,

admin template for manytomany

I have a manytomany relationship between publication and pathology. Each publication can have many pathologies. When a publication appears in the admin template, I need to be able to see the many pathologies associated with that publication. Here is the model statement:
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
def __unicode__(self):
return self.pathology
class Meta:
ordering = ["pathology"]
class Publication(models.Model):
pubtitle = models.TextField()
pathology = models.ManyToManyField(Pathology)
def __unicode__(self):
return self.pubtitle
class Meta:
ordering = ["pubtitle"]
Here is the admin.py. I have tried variations of the following, but always
get an error saying either publication or pathology doesn't have a foreign key
associated.
from myprograms.cpssite.models import Pathology
class PathologyAdmin(admin.ModelAdmin):
# ...
list_display = ('pathology', 'id')
admin.site.register(Pathology, PathologyAdmin)
class PathologyInline(admin.TabularInline):
#...
model = Pathology
extra = 3
class PublicationAdmin(admin.ModelAdmin):
# ...
ordering = ('pubtitle', 'year')
inlines = [PathologyInline]
admin.site.register(Publication,PublicationAdmin)
Thanks for any help.
Unless you are using a intermediate table as documented here http://docs.djangoproject.com/en/dev/ref/contrib/admin/#working-with-many-to-many-intermediary-models, I don't think you need to create an Inline class. Try removing the line includes=[PathologyInline] and see what happens.
I realize now that Django is great for the administration (data entry) of a website, simple searching and template inheritance, but Django and Python are not very good for complex web applications, where data is moved back and forth between a database and an html template. I have decided to combine Django and PHP, hopefully, applying the strengths of both. Thanks for you help!
That looks more like a one-to-many relationship to me, tho I'm somewhat unclear on what exactly Pathologies are. Also, so far as I understand, Inlines don't work on manytomany. That should work if you flip the order of the models, remove the manytomany and add a ForeignKey field to Publication in Pathology.
class Publication(models.Model):
pubtitle = models.TextField()
def __unicode__(self):
return self.pubtitle
class Meta:
ordering = ["pubtitle"]
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
publication = models.ForeignKey(Publication)
def __unicode__(self):
return self.pathology
class Meta:
ordering = ["pathology"]

Categories