问题
I am using django 1.7 with mongoengine. I have created a class Projects :
class Projects(Document):
user = ReferenceField(User, reverse_delete_rule=CASCADE)
p_name = StringField(max_length=70, required=True)
author = StringField(max_length=70, required=True)
url = StringField(max_length=200, required=True)
short_discription = StringField(max_length=100, required=True)
long_discription = StringField()
logo_url = StringField(max_length=200, required=False)
logo = ImageField(size=(250, 250, True))
tags = TaggableManager()
def __unicode__(self):
return self.p_name
def save(self, *args, **kwargs):
self.p_name = self.p_name
return super(Projects, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('view_project', args=[self.p_name])
def get_edit_url(self):
return reverse('update', args=[self.id])
def get_delete_url(self):
return reverse('delete', args=[self.id])
and i am referencing and storing user in my mongodb through my views :
class new_project(CreateView):
model = Projects
form_class = NewProjectForm
success_url = reverse_lazy('registered')
def get_template_names(self):
return["new_project.html"]
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super(new_project, self).form_valid(form)
and mongodb JSON format looks like this :
"user" : ObjectId("54db3e5d7818f4253e5da0db"),
I want to to create user profile where they can see their all projects, for that i created a view :
class UserProjectsListView(ListView):
model = Projects
context_object_name = "project"
def get_template_names(self):
return ["view_user.html"]
def get_queryset(self):
return self.model.objects.filter(user=self.kwargs['pk'])
and my urls.py :
url(r'^new_project/', new_project.as_view(),name='new_project'),
url(r'^project/(?P<pk>[\w\d]+)', view_project.as_view(), name='view_project'),
url(r'^user/(?P<pk>[\w\d]+)/$', UserProjectsListView.as_view(), name='detail'),
The problem with this is that i have to use the object id only in my url, but want to use username instead. Because on the template it renders only username not the object id.
Does anyone know how to use username in urls instead of object id, because rendering object id on template would not be good for security purpose also.
my user creation form :
class UserCreationForm(forms.Form):
error_messages = {
'duplicate_username': _("A user with that username already exists."),
'duplicate_email': _("A user with that email already exists."),
'password_mismatch': _("The two password fields didn't match."),
}
username = forms.RegexField(label=_("Username"), max_length=30,
regex=r'^[\w.@+-]+$',
help_text=_("Required. 30 characters or fewer. Letters, digits and "
"@/./+/-/_ only."),
error_messages={
'invalid': _("This value may contain only letters, numbers and "
"@/./+/-/_ characters.")})
email = forms.EmailField(label=_("Email"), max_length=254,
help_text=_("Required valid email. 254 characters or fewer."),
error_messages={
'invalid': _("This value may contain only valid email address.")})
password1 = forms.CharField(label=_("Password"),
widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password confirmation"),
widget=forms.PasswordInput,
help_text=_("Enter the same password as above, for verification."))
def clean_username(self):
# Since User.username is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
username = self.cleaned_data["username"]
try:
User._default_manager.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages['duplicate_username'],
code='duplicate_username',
)
def clean_email(self):
# Since User.username is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
email = self.cleaned_data["email"]
try:
User._default_manager.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError(
self.error_messages['duplicate_email'],
code='duplicate_email',
)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self):
user = User._default_manager.create_user(
username=self.cleaned_data['username'],
email=self.cleaned_data['email'],
password=self.cleaned_data["password1"])
return user
I also want to get data from three tables and i have used dev instead of class:
def UserProjectsListView(request, pk):
return render_to_response('view_user.html', {
'tuorial' : Tutorial.objects.filter(user=pk),
'question' : Question.objects.filter(user=pk),
'project': Project.objects.filter(user=pk),
})
P.S. Thanks in advance.
回答1:
If MongoEngine can't simulate joins, it is very simple to do this in two separate queries:
def get_queryset(self):
user = User.objects.get(username=self.kwargs['username'])
return self.model.objects(user=user.id)
来源:https://stackoverflow.com/questions/28694144/get-username-in-url-django-mongoengine