I'm a newbee to django and I'm trying to implement django models in django-admin.
Here is my models.py:
class Author(models.Model):
salutation = models.CharField(max_length=10)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
def __str__(self):
return self.first_name
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=100)
website = models.URLField()
def __str__(self):
return ' %s ----> %s' % (self.name, self.address)
class Book(models.Model):
title = models.CharField(max_length=30)
publication_date = models.DateField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
def __str__(self):
return self.title
In this when I create a new book through the admin site it should allow me to select one or more authors, but instead all the authors are selected automatically and there is no option to remove any. There is a plus sign to add more authors but none to remove the authors already related.
I want to have the particular authors that I select for any particular book.
I believe that you have misunderstood how the widget works.
Here is an example of the use of Django's default widget for a ManyToManyField
Example: a teacher model is related to a language model:
teaching_languages = models.ManyToManyField('Language')
In the following case, English and Spanish are selected as values related to the teacher model, whilst French and German are not selected.
The green + sign allows you to add another language to the teaching languages list.
Related
I am new to Django and I am trying to create a model for a website I am developing. So far I know how to implement everything I want to, but there is one thing that I cannot properly understand. So my idea is the following, in the models:
A class "Class" that can have as many "Teacher" and "Student" as wanted by the admin. I've been playing for a while with foreign key, but I can only manage to associate one student and teacher to a class, and whenever I want to display the "Class" info there is no Student or Teacher to display.
from django.db import models
from datetime import datetime
# Create your models here.
LANGUAGE_CHOICES = (
('english','ENGLISH'),
('spanish', 'SPANISH'),
('german','GERMAN'),
('french','FRENCH'),
('portuguese','PORTUGUESE'),
)
class Clase(models.Model):
name = models.CharField(max_length=300)
language = models.CharField(max_length=10, choices=LANGUAGE_CHOICES, default='english')
def __str__(self):
return self.name
class Student(models.Model):
name = models.CharField(max_length=300)
clase = models.ForeignKey(Clase, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Teacher(models.Model):
name = models.CharField(max_length=300)
total_earnings = models.IntegerField()
month_earnings = models.IntegerField()
clase = models.ForeignKey(Clase, on_delete=models.CASCADE)
def __str__(self):
return self.name
Since a Clase can have 'as many "Teacher" and "Student" as wanted' it may make sense to define the relationships with ManyToManyFields. I assume a Teacher and a Student can have more than 1 Clase?
class Clase(models.Model):
name = models.CharField(max_length=300)
language = models.CharField(max_length=10, choices=LANGUAGE_CHOICES, default='english')
students = models.ManyToManyField(Student)
teachers = models.ManyToManyField(Teacher)
def __str__(self):
return self.name
Then you can remove the foreign keys on the Student and Teacher models. Now when you edit a Clase in the admin you should be able to add as many students and teachers as you want
I am trying to create the proper Django model that could fit the following reqs:
Person Class has 1 to many relations with the Address Class
Person Class has many to many relations with the Group Class
Book Class contains the collections of the Persons and the Groups
This is my code:
class Person(models.Model):
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=20)
def __str__(self):
return self.first_name+ ' - ' + self.last_name
class Address(models.Model):
person = models.ForeignKey(Person)
address_line = models.CharField(max_length=200)
def __str__(self):
return self.address_line
class Group(models.Model):
group_name = models.CharField(max_length=12)
persons = models.ManyToManyField(Person)
def __str__(self):
return self.group_name
class Book(models.Model):
record_name = models.CharField(max_length=12)
person = models.ForeignKey(Person )
group = models.ForeignKey(Group )
def __str__(self):
return self.record_name
However it's not correct:
1) A Group can now contain multiple Persons but the Persons do not contain any Group.
I am not sure if I should add to the Person class the following code:
groups = models.ManyToManyField(Group)
2) The Book class now contains only 1 record of Person & Group per Book record.
3) When I added the Foreign Keys to the models, I removed
on_delete tag:
person = models.ForeignKey(Person, on_delete=models.CASCADE())
because it does not compile it, asking for some params.
I know how to make all this for C#, but I am a kinda stucked with this simple task in Python/Django.
1) The ManyToMany field should appear only in one of the models, and by looks of things you probably want it in the Person model.
Its important to understand that the data about the ManyToMany field is saved in a differant table. Django only allows this field to be visable through buth models (so basiclly, choose where it is move convinient).
2)By the look of your structure I will suggest you use a ManyToMany field through a different table. here is an example:
class Activity(models.Model):
name = models.CharField(max_length=140)
description = models.TextField(blank=True, null=True)
class Route(models.Model):
title = models.CharField(max_length=140)
description = models.TextField()
activities_meta = models.ManyToManyField(Activity, through = 'RouteOrdering')
class RouteOrdering(models.Model):
route = models.ForeignKey(Route, on_delete=models.CASCADE)
activity = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='activita')
day = models.IntegerField()
order = models.IntegerField(default=0)
that way the data is binded to the ManyToMany field
I have the following code in django
models:
class Book(models.Model):
book_id = models.CharField(max_length=10, primary_key=True)
title = models.CharField(max_length=255)
class Author(models.Model):
books = models.ForeignKey(Book)
author_name = models.CharField(max_length=200)
search_fields=['author_name']
class BookAdmin(admin.ModelAdmin):
model = Book
list_display=['book_id', 'title', 'get_author']
search_fields = ['title', 'book_id']
def get_author(self, obj):
names = [a.author_name for a in obj.author_set.all()]
return names
Is there any other way to display the list of authors in book admin page. As this result is giving output in unicode
Author name
[u'Zev Halevi']
[u'Kathryn Worth', u'Dorothy Bayley']
Also i need to provide a seperate search bar for searching through the authors. I am not able to use the author_name column as this is a foreign key
use this
def get_author(self, obj):
names = "\n".join([a.author_name for a in obj.author_set.all()])
return names
I have a polling app with one of the models "Choice" consisting of 2 Foreign key fields linked to the "Person" model.
I wanted to automatically populate related "photo_other" field (with the image link) once I have selected the "name" of the person. "name" is also a Foreign Key Field linked with Choice model.
models.py
class Choice(models.Model):
name = models.ForeignKey(Person)
photo_other = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
def __unicode__(self):
return smart_unicode(self.name)
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
def __unicode__(self):
return smart_unicode(self.name)
Why do you want to store the same value in two different tables when they are connected through a foreign key? It just doesn't make sense.
class Choice(models.Model):
name = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
#property
def photo_other(self):
return self.name.photo
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
In order to make photo_other visible under the admin page of Choice model, you can do the following;
class ChoiceAdmin(admin.ModelAdmin):
list_display = ['name', 'rating', 'get_photo']
def get_photo(self, obj):
return obj.photo_other
get_photo.short_description = 'Photo'
Greetings,
I'm sure there is a simple solution to what I'm trying to do but unfortunately I wasn't able to find it in the documentation.
I have the following model (simplified version shown):
models.py:
class Student(models.Model):
student_id = models.IntegerField(primary_key=True, unique=True,
db_index=True, max_length=9)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name)
class Course(models.Model):
course_id = models.AutoField(primary_key=True, unique=True,
db_index=True, max_length=4)
title = models.CharField(max_length=50)
dept = models.CharField(max_length=6)
number = models.IntegerField(max_length=5)
student_id = models.ManyToManyField(Student, blank=True)
def __unicode__(self):
return u"%s %s" % (self.dept, self.number)
What I wanted was to be able to add students to multiple classes in the admin interface similar to the way that I can add students in the classes admin interface. If there is yet another way that seems more beneficial I would be interested in that as well.
Thanks in advance for any help!
You can use the inlines in your related model, or this blog post might be of some help.