如何将 url 参数传递给视图以供其他类函数和模板使用
Posted
技术标签:
【中文标题】如何将 url 参数传递给视图以供其他类函数和模板使用【英文标题】:How to pass a url parameter into the views to be used by other class functions and the template 【发布时间】:2021-01-12 20:25:18 【问题描述】:请我有一个严重的问题,这几天给我留下了各种各样的错误。我想实现一些功能,但不知道如何实现。任何帮助将不胜感激。
我想创建一个注册表单,用于注册用户并在他们注册后将他们发送到他们的个人资料页面。我尝试通过尝试将用户填写表单的用户名传递给我的个人资料视图的 urls 参数来做到这一点。但是,我不确切知道如何执行此操作,并且我在网上找到的每个代码只会导致我出错。我是 Django 新手。
除此之外,我想创建我的个人资料视图,这样如果用户搜索他们自己的模板,那么他们可以编辑它,我为此使用了 UpdateView,如果它不是他们的个人资料,那么他们只能将其查看为只读的,我为此使用了 detailView。
另外,请有人也可以帮助我了解如何将 url 参数传递到基于类的视图中,视图中的所有功能如何访问此参数。如何在同一个基于类的视图中的另一个函数中使用基于类的视图中的函数的变量。也是使用 url 参数和重定向在不同视图之间传输变量的唯一方法。
请注意,我使用了自定义用户模型
这是我当前的错误
错误回溯
Traceback (most recent call last):
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\views\generic\base.py", line 73, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\views\generic\base.py", line 101, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\views\generic\edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "c:\MouauEasyGo\user\views.py", line 38, in form_valid
return HttpResponseRedirect(self.get_success_url())
File "c:\MouauEasyGo\user\views.py", line 55, in get_success_url
return reverse('profile', args=(self.kwargs['name_of_user']))
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\urls\base.py", line 87, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "C:\Users\Elisha\AppData\Local\Programs\Python\Python38\lib\site-
packages\django\urls\resolvers.py", line 685, in _reverse_with_prefix
raise NoReverseMatch(msg)
Exception Type: NoReverseMatch at /user/register/
Exception Value: Reverse for 'profile' with arguments '('a', 'g', 'e')' not found. 1 pattern(s) tried: ['user/profile/(?P<username>[^/]+)/$']
下面是我的代码
urls.py
from django.urls import path
from user import views as user_views
urlpatterns = [
path('profile/<str:username>/', user_views.profile_update_view.as_view(), name="profile"),
path('register/', user_views.user_register_view.as_view(), name="register"),
]
views.py
class user_register_view(CreateView):
template_name = "user/register.html"
form_class = UserRegistrationForm
model = NewUser
# I had to override the form_valid method and added form to the self parameter since get_success_url can't access form directly
def form_valid(self, form):
self.form = form
if form.is_bound:
self.kwargs['name_of_user'] = form.cleaned_data['user_name']
return HttpResponseRedirect(self.get_success_url())
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
try:
data['name_of_user'] = self.kwargs['name_of_user']
except KeyError:
return data
return data
def get_queryset(self):
qs = super().get_queryset()
return qs.filter(name__startswith=self.kwargs[self.request.user.user_name])
# if the user's username is in slug, then use it in the profile's url else then pick the username from the form and use instead
def get_success_url(self):
if self.kwargs['name_of_user']:
return reverse('profile', args=(self.kwargs['name_of_user']))
# this is the profile page as viewed by the owner of the profile
# the viewer passes the test only if they are the logged in user
# if they are not, then they are redirected to the the
# profile_detail_view.
class profile_update_view(UserPassesTestMixin, UpdateView):
model = Profile
fields = ['date_of_birth', 'country', 'about', 'image', ]
template_name = 'user/profile_update_form.html'
def get_object(self):
user = self.request.user
return get_object_or_404(Profile, pk=user.id)
# try to get the user_name from the current user.
# if the user is an Anoynmous user then just redirect to detail page
def test_func(self):
try:
x = self.request.user.user_name
y = self.kwargs.get('name_of_user')
if x == y:
return True
else:
return redirect('profile_detail_view.as_view()')
except AttributeError:
return redirect('profile_detail_view.as_view()')
# this is the profile page as viewed by the general public
# this view can only be reached if the current logged in user
# is not the one access the view
class profile_detail_view(DetailView):
template_name = "user/profile_detail.html"
model = Profile
def get_object(self):
user = self.request.user
return get_object_or_404(Profile.objects.get(pk=user.id))
forms.py
class UserRegistrationForm(UserCreationForm):
date_of_birth = forms.DateField(required=True)
country = forms.CharField(max_length=50, required=True)
image = forms.ImageField(required=False)
about = forms.CharField(widget=forms.Textarea, required=False)
class Meta:
model = NewUser
fields = ['email', 'user_name', 'first_name', 'last_name', ]
# save profile info as well as the user info in the form
def save(self, commit=True):
if not commit:
raise NotImplementedError(
"Can't create User and UserProfile without database save")
user = super(UserRegistrationForm, self).save(commit=True)
user_name = self.cleaned_data['user_name']
email = self.cleaned_data['email']
first_name = self.cleaned_data['first_name']
last_name = self.cleaned_data['last_name']
user, created = NewUser.objects.get_or_create(user_name=user_name, email=email, first_name=first_name, last_name=last_name)
user.save()
user_profile = Profile(
user=user,
about=self.cleaned_data['about'],
date_of_birth=self.cleaned_data['date_of_birth'],
country=self.cleaned_data['country']
)
user_profile.save()
return user, user_profile
models.py
class CustomAccountManager(BaseUserManager):
def create_superuser(self, email, user_name, first_name, last_name, password, **other_fields):
other_fields.setdefault('is_staff', True)
other_fields.setdefault('is_superuser', True)
other_fields.setdefault('is_active', True)
if other_fields.get('is_staff') is not True:
raise ValueError('Superuser must be assigned to is_staff=True.')
if other_fields.get('is_superuser') is not True:
raise ValueError(
'Superuser must be assigned to is_superuser=True.')
return self.create_user(email, user_name, first_name, last_name, password, **other_fields)
def create_user(self, email, user_name, first_name, last_name, password, **other_fields):
if not email:
raise ValueError(_('You must provide an email address'))
email = self.normalize_email(email)
user = self.model(email=email, user_name=user_name, first_name=first_name, last_name=last_name, **other_fields)
user.set_password(password)
user.save()
return user
class NewUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
user_name = models.CharField(max_length=150, unique=True)
first_name = models.CharField(max_length=150, unique=True)
last_name = models.CharField(max_length=150)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
objects = CustomAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['user_name', 'first_name', 'last_name']
def __str__(self):
return self.user_name
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(default="default.jpg", upload_to="profile image/")
about = models.TextField(_('about'), max_length=500, blank=True)
date_of_birth = models.DateField(default=timezone.now)
country = models.CharField(max_length=20, blank=True, null=True)
def __str__(self):
return f"self.user's profile"
我们将不胜感激。如果需要任何其他信息,请告诉我。提前感谢您的帮助。
【问题讨论】:
【参考方案1】:我举个例子:
模板:
<form method="GET" action="% url 'register' %">
<div class="input-group">
<input name="q" type="text" class="form-control" placeholder="Enter name..." />
<span class="input-group-append">
<input class="btn btn-secondary" type="submit" name="btn" value="Submit" />
</span>
</div>
</form>
网址:
path('register/', views.register, name='register'),
查看:
def register(request):
name = request.GET.get('q')
# redirect the page with this information.
实现this 的参考 - 查看此处执行的search
操作。
【讨论】:
谢谢。不敢相信这很容易。虽然我在保存表单后通过我的 form_valid() 方法自动登录用户解决了这个问题。然后使用不带参数的配置文件 url 将它们重定向到当前登录的用户,即填写表单的用户。如果有人想查看其他用户的个人资料,我还有另一个个人资料网址可以接受参数。这肯定会派上用场。谢谢以上是关于如何将 url 参数传递给视图以供其他类函数和模板使用的主要内容,如果未能解决你的问题,请参考以下文章