Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>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.)</p> <p>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.</p> <p>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:</p> <pre><code>@login_required def my_entries(request): user = request.user entries = Entry.objects.filter(created_by=user) # return response here... </code></pre> <p>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.</p> <p>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.)</p> <p>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.</p> <p>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:</p> <pre><code>@login_required def get_entry(request, entry_id): user = request.user entry = Entry.objects.get(id=entry_id, created_by=user) # return response here... </code></pre> <p>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:</p> <pre><code>@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... </code></pre> <p>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.</p> <p>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.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload