-5đź‘Ť
Use threadlocals if you want to get current user that edits this model. Threadlocals middleware puts current user into process-wide variable. Take this middleware
from threading import local
_thread_locals = local()
def get_current_user():
return getattr(getattr(_thread_locals, 'user', None),'id',None)
class ThreadLocals(object):
"""Middleware that gets various objects from the
request object and saves them in thread local storage."""
def process_request(self, request):
_thread_locals.user = getattr(request, 'user', None)
Check the documentation on how to use middleware classes. Then anywhere in code you can call
user = threadlocals.get_current_user
6đź‘Ť
This limiting of choices to current user is a kind of validation that needs to happen dynamically in the request cycle, not in the static Model definition.
In other words: at the point where you are creating an instance of this model you will be in a View and at that point you will have access to the current user and can limit the choices.
Then you just need a custom ModelForm to pass in the request.user to, see the example here:
http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/
from datetime import datetime, timedelta
from django import forms
from mysite.models import Project, TimeWorked
class TimeWorkedForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super(ProjectForm, self).__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(user=user)
class Meta:
model = TimeWorked
then in your view:
def time_worked(request):
form = TimeWorkedForm(request.user, request.POST or None)
if form.is_valid():
obj = form.save()
# redirect somewhere
return render_to_response('time_worked.html', {'form': form})
- Displaying multiple Rows and Columns in django-crispy-forms
- Changes made to (static) CSS file not reflecting in Django development server
- Call Django celery task by name
4đź‘Ť
Model itself doesn’t know anything about current user but you can give this user in a view to the form which operates models objects (and in form reset choices
for necessary field).
If you need this on admin site – you can try raw_id_admin
along with django-granular-permissions
(http://code.google.com/p/django-granular-permissions/ but I couldn’t rapidly get it working on my django but it seems to be fresh enough for 1.0 so…).
At last, if you heavily need a selectbox in admin – then you’ll need to hack django.contrib.admin
itself.
1đź‘Ť
Using class-based generic Views in Django 1.8.x / Python 2.7.x, here is what my colleagues and I came up with:
In models.py:
# ...
class Proposal(models.Model):
# ...
# Soft foreign key reference to customer
customer_id = models.PositiveIntegerField()
# ...
In forms.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.forms import ModelForm, ChoiceField, Select
from django import forms
from django.forms.utils import ErrorList
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from .models import Proposal
from account.models import User
from customers.models import customer
def get_customers_by_user(curUser=None):
customerSet = None
# Users with userType '1' or '2' are superusers; they should be able to see
# all the customers regardless. Users with userType '3' or '4' are limited
# users; they should only be able to see the customers associated with them
# in the customized user admin.
#
# (I know, that's probably a terrible system, but it's one that I
# inherited, and am keeping for now.)
if curUser and (curUser.userType in ['1', '2']):
customerSet = customer.objects.all().order_by('company_name')
elif curUser:
customerSet = curUser.customers.all().order_by('company_name')
else:
customerSet = customer.objects.all().order_by('company_name')
return customerSet
def get_customer_choices(customerSet):
retVal = []
for customer in customerSet:
retVal.append((customer.customer_number, '%d: %s' % (customer.customer_number, customer.company_name)))
return tuple(retVal)
class CustomerFilterTestForm(ModelForm):
class Meta:
model = Proposal
fields = ['customer_id']
def __init__(self, user=None, *args, **kwargs):
super(CustomerFilterTestForm, self).__init__(*args, **kwargs)
self.fields['customer_id'].widget = Select(choices=get_customer_choices(get_customers_by_user(user)))
# ...
In views.py:
# ...
class CustomerFilterTestView(generic.UpdateView):
model = Proposal
form_class = CustomerFilterTestForm
template_name = 'proposals/customer_filter_test.html'
context_object_name = 'my_context'
success_url = "/proposals/"
def get_form_kwargs(self):
kwargs = super(CustomerFilterTestView, self).get_form_kwargs()
kwargs.update({
'user': self.request.user,
})
return kwargs
In templates/proposals/customer_filter_test.html:
{% extends "base/base.html" %}
{% block title_block %}
<title>Customer Filter Test</title>
{% endblock title_block %}
{% block header_add %}
<style>
label {
min-width: 300px;
}
</style>
{% endblock header_add %}
{% block content_body %}
<form action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Save" class="btn btn-default" />
</form>
{% endblock content_body %}
- Best way to reference the User model in Django >= 1.5
- Stop nosetests from printing logging information?
- Django – how to filter out GET static and media messages with logging?
0đź‘Ť
I’m not sure that I fully understand exactly what you want to do, but I think that there’s a good chance that you’ll get at least part the way there using a custom Manager. In particular, don’t try to define your models with restrictions to the current user, but create a manager that only returns objects that match the current user.
- Call Django celery task by name
- Paypal monthly subscription plan settings for first day of the month and making monthly recurring payment – django python
- Is it ok to catch and reraise an exception inside Django transaction.atomic()?
-1đź‘Ť
Hmmm, I don’t fully understand your question. But if you can’t do it when you declare the model maybe you can achieve the same thing with overriding methods of the class of objects where you “send” the user object, maybe start with the constructor.
- Nginx Django and Gunicorn. Gunicorn sock file is missing?
- Override create method in django rest generics CreateAPIView