9š
Based on your requirements, having a different database table for each user would make things way more difficult, and it wouldnāt be worth the trade-off. As one example: in the āone table per userā scenario, when you go to retrieve the information for a user, you have to figure out what the name of that userās table is. Iām not even sure how you go about doing that, since the information about a user is stored in the table itself. (Ignoring session storage.)
An even bigger headache comes when you try to store the journal entries in their own table, and you want to maintain referential integrity. That is, you want to ensure that each entry belongs to a user that actually exists. That becomes almost impossible with a table for each user.
Itās easy to use one table for users, one table for entries, and to link the two without any large, gaping security holes. Your ācreated_byā link is the way to go. A view function to load a page can easily constrain the user so they only see their own entries. Hereās such a view:
@login_required
def my_entries(request):
user = request.user
entries = Entry.objects.filter(created_by=user)
# return response here...
The @login_required is a decorator that requires the user accessing the page be logged in, and the .filter() call on the Entry model will only load those entries that were created by the user who is loading the page.
Now, this list might link to an āeditā page for each entry. The URLs for each page will probably have a unique identifier in the URL, which is usually the ID field. So the first entry created with automatically get an ID of 1, the next one will get an ID of 2, and so on, so thereās something unique to identify each entry. So URLs might look like ā/entry/1/ā, ā/entry/2/ā, etc. When the page loads, it checks the ID in the URL. If itās ā1ā, it loads the entry with the ID of ā1ā for the user to edit. (Sorry if you already know that part.)
But, what that means is, a more savvy user might figure out how the URLs are formed and start putting in their own IDs, as a means of scouting for other peopleās entries. I could just start entering URLs with random ID values, until I find one that loads: ā/entry/8/ā. Maybe I donāt own the entry with an ID of 8, but in theory, if things are set up correctly, I could load it.
Thereās some pretty easy ways to thwart this. When you write the view for loading a single entry, donāt just load the Entry instance by its IDā¦load it by its ID and the user it was created by:
@login_required
def get_entry(request, entry_id):
user = request.user
entry = Entry.objects.get(id=entry_id, created_by=user)
# return response here...
In the above case, if I tried to load this page for an entry that exists, but that doesnāt belong to me, an exception will be raised. Thereās actually a helper method in Django called āget_object_or_404ā that helps with this:
@login_required
def get_entry(request, entry_id):
user = request.user
entry = get_object_or_404(Entry, id=entry_id, created_by=user)
# return response here...
Now, if I try to access the page for an Entry instance that exists, but isnāt mine, Iāll just see the typical āPage Not Foundā error that Django would offer if I tried to access a page that didnāt exist.
I know your question was about the user database tables, but I hope this helps you configure Django so that your users arenāt reading/editing each otherās data.
3š
No, a table per user is the exact opposite of best practice. Normalize the data by adding a ācreated_byā column or similar.
- [Django]-Stop celery task from django admin panel
- [Django]-How to use SearchHeadline with SearchVector on multiple fields
- [Django]-Renderer returned unicode, and did not specify a charset value
3š
Why not create a table per user?
Creating a db table per user is definitely not recommended.
How would you create a table for every user? Raw SQL statements? As far as I know, you would break the main purpose of Django, itās ORM (object relational mapper) ā itās easy interface to SQL because it doesnāt support automatically creating tables per user / knowing how to query it.
Definitely, definitely use a table with a ForeignKey
to the User
table.
Every table has a Primary Key field which is generally a number. One table can refer to another table via that Primary Key.
For example Entry 1 belongs to User ID 3
.
Luckily, django abstracts the SQL layer and this is done via the ForeignKey
field.
http://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey
As you are the one constructing queries for the database, only showing entries written by a specific user is a non-issue. You would simply only query the database for entries by the logged in user. As long as there are no loopholes for raw SQL to be input from outside your program, thereās no way a user can access others data.
To learn about best practice / ForeignKeyās / querying etc, I suggest following the tutorial online. I think the documentation and tutorials are one of djangoās greatest assets.
http://docs.djangoproject.com/en/dev/intro/tutorial01/
In the first tutorial they cover creating a Poll
app, which includes a Choices
model with a ForeignKey
to Poll
You can definitely apply this back to your model : )
2š
Well you have to have a field in your model which would hold the userid. ( This means one table. Creating a table per person isnāt a good idea.)
Then youād have to apply some permissions so that that user may only see what he has composed and other people can not see what he has written.
These links are very helpful regarding row level permissions.
http://code.djangoproject.com/wiki/RowLevelPermissions
http://djangosnippets.org/snippets/1054/ This one is the one I used and found very helpful.
http://code.djangoproject.com/wiki/RowLevelPermissionsDeveloper
- [Django]-Internet Explorer does not talk with django dev server
- [Django]-Django url rewrite without redirect
- [Django]-Django ā Using F() expression but obtaining non atomic update
- [Django]-Improve django queryset performance
- [Django]-CSS file not found. Django project
1š
Like the others have said, even trying to create a table per user in django would be difficult.
Generally when working with relational databases, if you try the one table per user, youāll only try it once. š Imagine if you started scaling to a few hundred users and now you have a requirement to get a count of all entries. You want to do 300 queries for that? Maybe a massive query with 300 UNION ALL statements? Not only will performance suffer, but youāll get tired of maintaining the app as well.
Because you havenāt worked with databases much, you might want to read up a little on the relational data model a little bit. You could pick up a decent book on it, Database Design For Mere Mortals or maybe a tutorial online like: http://www.15seconds.com/issue/020522.htm. Get some background on RDBMS design and then come back to the django tutorial and it will make sense.
- [Django]-OperationalError: (2019, ""Can't initialize character set utf8mb4 (path: C:\\mysql\\\\share\\charsets\\)"")
- [Django]-Formatting inline many-to-many related models presented in django admin
- [Django]-How to pull information saved from IP address call with GeoIP2() django models to display in my html
- [Django]-What is the best way to consume a django-piston REST API from a Django view?