I have three classes:
Person
Publication
AuthorOrder
Publication has a m2m field to Person through AuthorOrder. This is done to enable making it possible to set the order of authors, which matters for academic publications.
However, the list of Persons is getting long, and it would therefore be nice if it was searchable or at least sorted. However, if I use the obvious method of setting a Meta class to Person, this causes the Persons to be sorted everywhere, including where I don't want them to be.
Is there a way to make it searchable (best) or at least sorted without ruining the order elsewhere (ok)?
Looks like this:
There you go. This works well for us on several projects. https://github.com/and3rson/django-searchable-select
Related
I searched on google and found this: "SlugField is a field for storing URL slugs in a relational database. SlugField is a column defined by the Django ORM. SlugField is actually defined within the django.db."
But still, the definition sounds a little complicated to me. I don't even know what a slug is in this context and not sure about Django ORM.
I just need a reason why I should use SlugField in Django in simple terms.
You don't strictly need to use a SlugField.
"Slug" is a term borrowed from journalism that refers to a short version of a title. As mentioned in a comment to your answer, it's a way to make URLs more explicit while still keeping them somewhat short, instead of using, for example, the full title (which would often be too long), or an ID (which wouldn't be explicit or memorable at all: think of a user who wants to find an article they remember reading: if they start typing some keyword in their address bar, a URL that contains it will pop up, one with an ID will not).
If you wanted you could craft your own slug, by making it URL-friendly (remove any symbol that a URL wouldn't hold, converting anything that would need to be url-encoded, turning spaces into hyphens...) and removing anything unnecessary (e.g. removing words like the, a, an, is, are... or cropping lenghty titles to a maximum number of words or characters).
SlugField is simply a convenience you can use to automate that to some extent. It also comes with some extra features that you might need: for example it automatically generates a slug from a field of your choice, and it can add a unique number to the slug so that you don't accidentally end up with two identical URLs for two different articles that have the same title.
The reason it is a field is that, although you could, it's not smart to calculate a slug every time you access an object: the slug will only change when the title changes, meaning possibly never, so it makes sense to generate it only once and then store it in the database to use it next time, without having to produce it again. This has the added advantage of making a URL to a certain article permanent: you could make it so the slug won't change even if you change the title of the article, which would be a good thing.
Once you have it, since a slug refers unambiguously to a specific object, it acts as a sort of human-readable unique ID, and so it can be used to retrieve the object from the database as efficiently as an opaque numeric ID. It also obscures how many objects you have (if for some reason you want to do that), since a sequential ID of, say, 1543, tells anyone that you probably have 1542 other objects that came before that one.
I searched a lot and did not find what I´am looking for.
What would be the best concept for a model class in django?
To extend User, would be better to have a class with several attributes, or break this class into several classes with few attributes? I´m using the django ORM now.
Say I have a class called Person that extends User, would be better:
class Person(models.Model):
user = foreingkey(User)
attribute1 =
...
attributeN =
Or, would it be better to do this:
class PersonContac(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
class PersonAddress(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
class PersonHobby(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
My each of my views would use the data from the smaller classes (probably).
Over time, the atrribute number can expand.
I want to do is do it once, and touch the minimum possible.
Various attributes can be unfilled by the user, they are not required.
The number of user is indefinite (can be a lot).
I´m concerned in terms of long term performance and maintaining.
If someone can explain me, what would be better for my code, and why.
And what would be better in general (less classes/more attributes, or more classes/less attributes), using the Django ORM.
It is better if my views use the data of only one model class, or it makes no (or little) difference?
Edit:
On the rush for writing I used bad names on class. None of these attributes are many-to-many fields, the User will have only one value for each attribute, or blank.
The number of atributes can expand over time, but not in a great number.
Put any data that is specific to only one User directly in the model. This would probably be things like "Name", "Birthday", etc.
Some things might be better served by a separate model, though. For example multiple people might have the same Hobby or one User might have multiple Hobby(s). Make this a separate class and use a ForeignKeyField or ManyToManyField as necessary.
Whatever you choose, the real trick is to optimize the number of database queries. The django-debug-toolbar is helpful here.
Splitting up your models would by default result in multiple database queries, so make sure to read up on select related to condense that down to one.
Also take a look at the defer method when retrieving a queryset. You can exclude some of those fields that aren't necessary if you know you won't use them in a particular view.
I think it's all up to your interface.
If you have to expose ALL data for a user in a single page and you have a single, large model you will end up with a single sql join instead of one for each smaller table.
Conversely, if you just need a few of these attributes, you might obtain a small performance gain in memory usage if you join the user table with a smaller one because you don't have to load a lot of attributes that aren't going to be used (though this might be mitigated through values (documentation here)
Also, if your attributes are not mandatory, you should at least have an idea of how many attributes are going to be filled. Having a large table of almost empty records could be a waste of space. Maybe a problem, maybe not. It depends on your hw resources.
Lastly, if you really think that your attributes can expand a lot, you could try the EAV approach.
In a Google App Engine solution (Python), I've used the db.ListProperty as a way to describe a many-to-many relation, like so:
class Department(db.Model):
name = db.StringProperty()
#property
def employees(self):
return Employee.all().filter('departments', self.key())
class Employee(db.Model):
name = db.StringProperty()
departments = db.ListProperty(db.Key)
I create many-to-many relations by simply appending the Department key to the db.ListProperty like so:
employee.departments.append(department.key())
The problem is that I don't know how to actually remove this relationship again, when it is no longer needed.
I've tried Googling it, but I can't seem to find any documentation that describes the db.ListProperty in details.
Any ideas or references?
The ListProperty is just a Python list with some helper methods to make it work with GAE, so anything that applies to a list applies to a ListProperty.
employee.departments.remove(department.key())
employee.put()
Keep in mind that the data must be deserialized/reserialized every time a change is made, so if you are looking for speed when adding or removing single values you may want to go with another method of modelling the relationship like the one in the Relationship Model section of this page.
The ListProperty method also has the disadvantage of sometimes producing very large indexes if you want to search through the lists in a datastore request.
This may not not be a problem for you since your Lists should be relatively small, but it's something to keep in mind for future projects.
Found it via trial and error:
employee.departments.remove(department.key())
Lets say I have three django model classes - lets call them A, B and C. If A and B are abstract, I can do something like:
class C(A,B):
pass
What if they aren't abstract and I do the same? Will everything still work correctly or no? Or have I got it wrong and this should not be done with abstract models either?
I'm having some issues which I'm attributing to the fact that the answer is probably no, but I'd still prefer to make sure about this if anyone knows :)
The specific use case I had for this is probably better served by Generic Relations (I only recently discovered their existence), so I guess it would be understandable if the Django team made a design decision like this (I can't see many people needing to do this). I'd just like to know for sure what the case is.
Edit 1 (after Dominic's answer)
Interesting... The problem we're having is a structure similar to IMDb (I think IMDb is a bit easier to understand than the topic matter we actually have, so I'll use them as an example). On IMDb they have pages for People and pages for Movies and both People and Movies have their own message boards.
We've ended up connecting message boards to the People and Movies by creating a model called MessageboardOwner (with only one attribute - the id added automatically by Django), which "owns" the message board and People and Movies inherit it. The problem is that our "People" class inherits from two other classes also. The class definition is something like:
class Person(A,B,MessageboardOwner):
Initially this seemed to work out fine, but then today something rather weird happened... I was deleting a Person in the admin and the admin asked the "Are you sure?" question and was showing me what other objects it would have to delete. It was trying to delete two message boards, not one. One of these message boards should have been owned by a Movie, not a Person.
Upon looking at what exactly was in the database, I found that this Person instance was using the same MessageboardOwner instance as the Movie was. When I played around with it, what came out was that the Movie class, which inherited only after MessageboardOwner, seemed to work ok. Saving the Person, however, only created a MessageboardOwner object if one didn't already exist (or possibly overwrote the existing one - I'm not sure). I also found that the id fields inherited from A, B and MessageboardOwner were always equal, which seemed strange to me.
Yes, you can use normal Python multiple-inheritance with models. Bear in mind this warning though:
Just as with Python's subclassing,
it's possible for a Django model to
inherit from multiple parent models.
Keep in mind that normal Python name
resolution rules apply. The first base
class that a particular name (e.g.
Meta) appears in will be the one that
is used; for example, this means that
if multiple parents contain a Meta
class, only the first one is going to
be used, and all others will be
ignored.
Generally, you won't need to inherit
from multiple parents. The main
use-case where this is useful is for
"mix-in" classes: adding a particular
extra field or method to every class
that inherits the mix-in. Try to keep
your inheritance hierarchies as simple
and straightforward as possible so
that you won't have to struggle to
work out where a particular piece of
information is coming from.
From the Django docs.
Generally, multiple inheritance is a bad idea, and there are simpler ways to do things. If you flesh out what problem you're trying to solve a bit more clearly, we might be able to help a bit better.
I have the following problem and I'm wondering if there's a nice way to model these objects without using multiple inheritance. If it makes any difference, I am using Python.
Students need contact information plus student information. Adults need contact information plus billing information. Students can be adult students, in which case I need contact/student/billing info, or they can be children, in which case I need contact/student/parent info.
Just to be clear on how the system will be used, I need to be able to ask for a list of all adults (and I will get adult students plus parents), or a list of all students (and I will get child students plus adult students).
Also, all of these objects need to have a common base class.
What you have is an example of Role -- it's a common trap to model Role by inheritance, but Roles can change, and changing an object's inheritance structure (even in languages where it's possible, like Python) is not recommended. Children grow and become adults, and some adults will also be parents of children students as well as adult students themselves -- they might then drop either role but need to keep the other (their child changes schools but they don't, or viceversa).
Just have a class Person with mandatory fields and optional ones, and the latter, representing Roles, can change. "Asking for a list" (quite independently of inheritance or otherwise) can be done either by building the list on the fly (walking through all objects to check for each whether it meets requirements) or maintaining lists corresponding to the possible requirements (or a mix of the two strategies for both frequent and ad-hoc queries). A database of some sort is likely to help here (and most DBs work much better without inheritance in the way;-).
As I'm sure someone else will comment soon (if they haven't already), one good OO principle is "Favor composition over inheritance". From your description, it sounds suspiciously like you're breaking the Single Responsibility Principle, and should be breaking down the functionality into separate objects.
It also occurs to me that Python supports duck typing, which begs the question "Why is it so important that all the classes have a common base class?"
Very simple solution: Use composition rather than inheritance. Rather than having Student inherit from Contact and Billing, make Contact a field/attribute of Person and inherit from that. Make Billing a field of Student. Make Parent a self-reference field of Person.
It doesn't sound like you really need multiple inheritance. In fact, you don't ever really need multiple inheritance. It's just a question of whether multiple inheritance simplifies things (which I couldn't see as being the case here).
I would create a Person class that has all the code that the adult and student would share. Then, you can have an Adult class that has all of the things that only the adult needs and a Child class that has the code only the child needs.
This sounds like something that could be done quite nicely and flexibly with a component architecture, like zope.components. Components are in a way a sort of super-flexible composition patterns.
In this case I'd probably end up doing something when you load the data to also set marker interfaces on it depending on some information, like if age >= 18 you set the IAdult interface, etc. You can then get the adult information by doing
adultschema = IAdultSchema(person)
or something like that.
(Edit: Actually I'd probably use
queryAdapters(person, ISchema)
to get all schemas in one go. :)
A component architecture may be overkill, but once you got used to thinking like that, many problems get trivial. :)
Check out Brandons excellent PyCon talk about it: http://www.youtube.com/watch?v=UF77e2TeeQo
And my intro blog post: http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/
I think your requirements are over-simplified, since in a real situation, you might have students with their own accounts to handle billing even if they are minors who need parent contact information. Also, you might have parental contact information be different from billing information in an actual situation. You might also have adult students with someone else to bill. BUT, that aside - looking at your requirements, here is one way:
classes: Person, BillingInfo, StudentInfo.
All people are instances of class Person...
class Person:
# Will have contact fields all people have - or you could split these off into an
# object.
parent # Will be set to None for adults or else point to their parent's
# Person object.
billing_info # Set to None for non-adults, else to their BillingInfo object.
student_info # Set to None for non-student parents, else to their StudentInfo
# object.
Checking the fields will allow you to create lists as you desire.
One solution is to create a base Info class/interface that the classes ContactInfo, StudentInfo, and BillingInfo inherit from. Have some sort of Person object that contains a list of Info objects, and then you can populate the list of Info objects with ContactInfo, StudentInfo, etc.
In pseudocode, you could do something like this:
Class Student
Inherits WhateverBase
Private m_StudentType as EnumStudentTypes 'an enum containing: Adult, Child
Private m_Billing as Billing
Private m_Contact as Contact
Private m_Parent as Parent
Public Sub Constructor(studentType, billing, contact, parent)
...logic to make sure we have the right combination depending on studentType.
...throw an exception if we try to assign a a parent to an adult, etc.
...maybe you could have seperate constructors, one for each studenttype.
End Sub
Public Property StudentType as EnumStudentTypes
Get
Return m_StudentType
End Get
End Sub
Public Property Parent
Get
...code to make sure we're using a studentType that has a parent,
...and throws an exception if not. Otherwise it returns m_Parent
End Get
End Sub
[more properties]
End Class Student
Then you could create a class called StudentManager:
Public Class StudentManager
Public Function GetAdults(studentCollection(Of Students)) as StudentCollection(Of Students)
Dim ResultCollection(Of Students)
...Loop through studentCollection, adding all students where Student.StudentType=Adult
Return ResultCollection
End Function
[Other Functions]
End Class
Public Enum StudentType
Adult=0
Child=1
End Enum