2014-10-10 2 views
0

Я создаю приложение Django, где пользователи могут создавать учетные записи для них, а затем добавлять транзакции в каждую учетную запись. Его часть сайта, которая позволит пользователям отслеживать прирост инвестиций. Для этого я использую общие представления классов.Ограничение доступа к общим представлениям Django

Пользователи добавляют транзакции к определенной учетной записи (код не показан), а затем они должны иметь возможность просматривать транзакции для этой конкретной учетной записи с использованием сайта/транзакций/2 /, где 2 - идентификатор учетной записи.

Проблема заключается в том, что любой зарегистрированный пользователь может просто изменить URL-адрес, чтобы получить транзакции с учетной записью другого пользователя. Я могу легко исправить это, установив, что данный идентификатор учетной записи принадлежит пользователю, но я думаю, что должен быть лучший способ. Есть ли лучшие способы, как я могу это достичь? Должен ли я, возможно, не кодировать URL? Я не так увлекаюсь идеей, что пользователи все равно видят свои идентификаторы учетной записи в БД.

Кроме того, на более позднем этапе я хочу, чтобы пользователи могли просматривать транзакции своих счетов в одном списке. Например, показать все транзакции для 3 из их 5 учетных записей. Тогда этот метод URL также не будет работать. Какие еще варианты у меня есть?

В models.py у меня есть:

class Account(models.Model): 
    name = models.CharField(max_length=40, unique=True, db_index=True) 
    user = models.ForeignKey(User) 

class Transaction(models.Model): 
    value = models.DecimalField(max_digits=15, decimal_places=2) 
    date = models.DateField('transaction date') 
    account = models.ForeignKey(Account) 

В urls.py:

url(r'^(?P<account_id>\d+)/$', views.IndexView.as_view(), name='index'), 

В views.py:

class IndexView(LoginRequiredMixin, generic.ListView): 
    model = Transaction 

    def get_queryset(self): 
     account_id = self.kwargs['account_id'] 
     queryset = Transaction.objects.filter(account_id=account_id) 
     return queryset 

А то у меня есть transaction_list шаблон

Thanks

ответ

1

Вы можете использовать вспомогательную функцию get_object_or_404(), чтобы сначала получить объект учетной записи, если вы хотите иметь ошибку 404.

Как это:

def get_queryset(self): 
    account_id = self.kwargs['account_id'] 

    # raise 404 if no account is found for the current user 
    account = get_object_or_404(Account, pk=account_id, user=self.request.user) 

    queryset = Transaction.objects.filter(account=account) 
    return queryset 

Для вашей второй вещи, которую вы упомянули, вы можете либо создать новый вид, или просто проверить, если 'account_id' был в URL, и повторно использовать текущий вид. Вам понадобится новый URL-адрес в любом случае.

urls.py:

url(r'^(?P<account_id>\d+)/$', views.IndexView.as_view(), name='index'), 
url(r'^$', views.IndexView.as_view(), name='index'), 

измените get_queryset() снова в случае, когда нет идентификатор счета не в URL:

def get_queryset(self): 
    # account_id will be None if the second url was the one that matched. 
    account_id = self.kwargs.get('account_id', None) 

    if account_id: 
     # raise 404 if no account is found for the current user 
     account = get_object_or_404(Account, pk=account_id, user=self.request.user) 

     queryset = Transaction.objects.filter(account=account) 
    else: 
     # we're going to show all transactions for the user, rather than a specific account 
     queryset = Transaction.objects.filter(account__user=self.request.user) 

    return queryset 
+0

спасибо! Я думаю, что это нужно. Я довольно новичок в django, поэтому мне интересно, хорошо ли использовать идентификаторы полей базы данных в URL-адресе, например, в этом примере? – Johan

+0

Его довольно стандартный, да. Лучше, более дружелюбным способом может быть использование пули вместо этого. Но я не думаю, что его плохая практика - использовать идентификатор. – jproffitt