Storing several informations in one variable in Django Models - python

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()

Related

Django - Foreign key referencing one of two tables depending on its content

I've hit a dead end in my database-model design and could use some help.
We are using a Postgres database and django framework to store a variety of papers, books etc.
These are the base classes I'm having trouble with:
class Publisher(models.Model):
name = models.CharField(unique=True)
website = models.URLField(blank=True)
#...
class Editor(models.Model):
firstname = models.CharField()
lastname = models.CharField()
#...
class Book(models.Model):
title = models.CharField(unique=True)
#...
editors = models.ManyToManyField(Editor, blank=True)
publisher = models.ForeignKey(Publisher, blank=True)
#...
The Editor class above is modeled to store the editor(s) as persons of a corresponding book eg. "Ryan Carey" or "Nicholas Rowe".
The Publisher class would hold information like "University of Chicago Press".
The problem hatches should the Editor and Publisher be the same.
For example should the Editor and Publisher both be "University of Chicago Press".
Now, whenever a new Book is saved to the database through the django-admin interface I would like following to happen:
If one or more Editors are given, save it as in the model above.
If no Editors are given but a Publisher is given then make editors point to the same key publisher is pointing to
If none of both are given leave both blank
I was thinking of implementing it somehow like this:
class Book:
#...
def save(self, *args, **kwargs):
if self.editors.count() <= 0 and self.publisher:
self.editors = self.publisher #This is not possible
super(Book, self).save(*args, **kwargs)
The self.editors = self.publisher bit could perhaps be fixed with inheritance, but there are still multiple editors and just one publisher and I dont want publishers and editors to be stored int he same table.
Any thoughts on how to approach this?
With little of re-structuring your models, is possible and will be more flexible than now.
First: don't put publisher and editor to 2 separate models. Make one.
Second: if you can have publisher/editor both person and organization/company (and that will require different model fields), put all common fields into one model and make 2 models that will inherit from that model, containing more specified fields. That will create under the hood one-to-one relation between fields.
Third: create 2 fields in your book model, one ForeignKey named publisher and one ManyToMany named editors. Both relations should point to your base model for publisher/editor.
Sample code:
class PEBase(models.Model): # have no idea how to name it better
some_common_field = models.Field(...)
class PEPerson(PEBase):
first_name = models.CharField()
last_name = models.CharField()
class PEOrganization(PEBase):
name = models.CharField()
website = models.URLField()
class Book(models.Model):
title = models.CharField(unique=True)
#...
editors = models.ManyToManyField(PEBase, blank=True, related_name="books_edited")
publisher = models.ForeignKey(PEBase, blank=True, related_name="books_published")
def save(self, *args, **kwargs):
super(Book, self).save(*args, **kwargs)
if self.editors.count() <= 0 and self.publisher:
self.editors.add(self.publisher) #This must go after save - ID of book must be already set.

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

Python Django how to retrieve specific objects

I've got this Post model at the moment:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
If I've got different parts of a website (or a forum rather) that contain different posts, e.g. Discussion about basketball, and Discussion about football, if I wanted to return just posts concerning basketball or just posts concerning football, is the easiest way to just make a specific basketball_post model/football_post model or is there a more efficient way? Should I perhaps be storing the values differently?
Thanks
Django has a really good tutorial. It is about making a Poll app. In the first chapter the thing you want is discussed. It is about a Question that can have multiple Choices.:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
The foreignKey creates a relation between two models. The same can be done for a blog:
class Category(models.Model):
title = models.CharField(max_length=200)
class Post(models.Model):
category = models.ForeignKey(Category) # This is the important part.
title = models.CharField(max_length=200)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
The ForeignKey relation lets you do really nice things:
basketball_posts = Post.objects.filter(category_title='Basketball')
But before we all tell you how it is done, I really recommend to do the tutorial. It introduces you to all important Django concepts: https://docs.djangoproject.com/en/1.7/intro/tutorial01/
Update
If you have a fixed set of categories that are not likely to change, than you can hardcode them and use field choices:
class Post(models.Model):
FOOTBALL = 'F' # Variable name and db_value
CRICKET = 'C'
INTRODUCTION = 'I'
CATEGORY_CHOICES = (
(FOOTBALL, 'Soccer'), # Variable name and display value
(CRICKET, 'Cricket'),
(INTRODUCTION, 'Hello my name is'),
)
category = models.CharField(max_length=1,
choices=CATEGORY_CHOICES,
default=INTRODUCTION)
...
https://docs.djangoproject.com/en/dev/ref/models/fields/#choices
One of the advantages of this 'choice machinery' over a CharField without pre defined choices is that you are sure what values end up in your database. This lets you query them, without worrying if your data is sane:
Post.objects.filter(category=Post.CRICKET)
Use the extra table if you need the freedom to create new categories in the future. Use field choices if you don't want (or need) that freedom.
I would suggest to just add a field which makes the post relevant to that certain topic:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
type = models.CharField(max_length=20) #<--- new field: e.g 'basketball','hockey'..
def __unicode__(self):
return self.title
example query:
#basketball posts
qs = Post.objects.filter(type__icontains="basketball")
then you dont need to have multiple models which also would be redundant.
Assuming all of the posts are in the same format, you could add another field to your model like "type". Different discussion forums could send a different values for that field when the post is added.
type = models.CharField(max_length=140, choices=['Football', 'Basketball', 'Baseball'])
Storing this would make it easy to filter which posts are which.
Post.objects.filter(type = 'Football')
Assuming that one post can be about only one sport, the better approach would be to have a foreign key relation between a model that stores data about a post with another model that stores the data about sports.
Something like this
class Sport(models.Model):
name = models.CharField(max_length = 200)
description = models.TextField()
def __unicode__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
sport = models.ForeignKey(Sport)
def __unicode__(self):
return self.title
This gives you the advantage of isolating the 'Sport' and the 'Post' models.You can add as many sports as you want, without any posts referring to it.
One more advantage is that you can add relevant information to the relevant models.
Eg:Suppose you want to add the information about "how many players are there in a team for sport x?". You can easily achieve this by adding a field "number_of_players" in the 'Sport' model without affecting the 'Post' model.
If you had to do this in one model, 'Post', then it would create lot of issues in terms of data consistency and other undesirable things.
Also, the query will look something like this:
posts = Post.objects.filter(sport__name = "Basketball")
PS:If your requirement is that a post can be tagged to multiple sports, then you can use ManyToMany field instead of a simple foreign key.
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
You could assign your posts tags or category, and filter on those.
If you use the model approach what happens when you add more sports? You'll need manually add the sports in your code, using a tags or category approach allows you to handle it in the db, and would then allow you to filter on the tags/categories in your system

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,

django admin inline components

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.

Categories