Как отправить проверку электронной почты из админки при обновлении электронной почты
Я присоединился к проекту, где код написан на django 2+. Это система для пациентов и врачей. Когда врач регистрирует пациента, тот получает подтверждение по электронной почте со ссылкой. Как только он нажимает на нее, она может использовать платформу.
На пользовательском интерфейсе в настройках пациентка может обновить свой email, и она получит новую ссылку на свой новый email для подтверждения того, что это ее email. До того, как она нажмет на ссылку подтверждения, атрибут email не изменяется. обновляется только кандидат email и на него отправляется письмо. (если я изменю атрибут email на email_кандидата, то если она ошибется в email_кандидата, она больше не сможет войти в систему)
После клика электронная почта пациента станет электронной почтой кандидата.
Все это работает
В интерфейсе администратора поддержки пациентов агент может помочь пациентам обновить их электронную почту. Но когда запрашивается действие отправки подтверждения электронной почты, кандидат на электронную почту не выбирается. Выбирается только электронная почта пользователя, на которую отправляется подтверждение электронной почты.
Я действительно не понимаю, как вызвать, возможно, ту же функцию обновления электронной почты.
models.py User
class User(AbstractUser):
objects = UserManager()
is_physician = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
title = models.CharField(choices=TITLE_CHOICES,
max_length=10,
blank=True,
null=True)
first_name = models.CharField(max_length=254, blank=True, null=True, )
last_name = models.CharField(max_length=254, blank=True, null=True, )
birthdate = models.DateField(null=True, blank=True)
home_phone = PhoneNumberField(blank=True, null=True)
mobile_phone = PhoneNumberField(blank=True, null=True)
gender = models.CharField(max_length=1,
choices=GENDER_CHOICES,
blank=True,
null=True)
language = models.CharField(max_length=4,
choices=settings.LANGUAGES,
default='en',
blank=True,
null=True)
email = models.EmailField(unique=True, db_index=True,
error_messages={
'unique': "Email already exists."
}
)
email_candidate = models.EmailField(
max_length=254,
blank=True,
null=True,
default=None)
username = models.CharField(
max_length=30,
unique=True,
blank=True,
null=True,
validators=[
validators.RegexValidator(
r'^\w+$',
'Enter a valid username. This value may contain only '
'letters, numbers and _ character.',
'invalid'
),
],
error_messages={
'unique': "Username already exists."
}
)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
ordering = ('created',)
class Meta(object):
verbose_name = 'User'
verbose_name_plural = 'Users'
# abstract = False
permissions = u_perm.user_permissions
@property
def name(self):
return '{} {}'.format(self.last_name, self.first_name, )
models.py У пациента есть поле OneToOne user
class Patient(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
physician = models.ForeignKey(Physician,
related_name='patients',
null=True,
blank=True,
on_delete=models.SET_NULL)
address = models.TextField(blank=True, null=True)
city = models.CharField(max_length=85, null=True, blank=True)
country = CountryField(null=True, blank=True)
postal_code = models.CharField(max_length=32, null=True, blank=True)
reminder_hour_default = models.TimeField(
'Send Reminder Time',
default=settings.REMINDER_HOUR_DEFAULT)
is_eligible = models.BooleanField(default=True)
def __str__(self):
return self.user.email
@receiver(post_save, sender=Patient)
@receiver(post_save, sender=User)
def update_status(sender, **kwargs):
def update_patient(instance):
# from pending/disabled to active
current_status = instance.user.status
instance.save()
instance.user.save()
return
def update_user(instance):
pass
instance = kwargs.get('instance')
method_name = get_inner_method(sender)
if instance and method_name:
method_name(instance)
models.py Patient Support
class PatientSupport(Patient):
class Meta:
proxy = True
# Add verbose name
verbose_name = 'Patient Support'
verbose_name_plural = 'Patients Support'
serializers.py UserSerializer с рабочей конечной точкой из пользовательского интерфейса пациента под названием update_candidate_email
admin.py PatientSupportAdmin оттуда мне нужно обновить email, отправив подтверждение электронной почты на email_candidate
class PatientSupportAdmin(admin.ModelAdmin):
list_display = ['pk', 'patient', 'patient_email', 'email_candidate' ]
list_display_links = ('pk', 'patient')
def get_queryset(self, request):
qs = super(PatientSupportAdmin, self).get_queryset(request)
return qs.filter(support_consent=True)
fieldsets = (
('User', {
'fields': (
'patient',
'get_gender',
'birthdate',
'home_phone', 'mobile_phone', 'language',
'email', 'username',
'date_modified',
'date_joined',
'status',
'user',
)}),
('Patient', {'fields': ('physician',
'country',
'id_number',
)}),
def patient(self, obj):
return obj.user.get_full_name()
def patient_email(self, obj):
return obj.user.email
def email_candidate(self, obj):
return obj.user.email_candidate
def birthdate(self, obj):
return obj.user.birthdate or ''
def home_phone(self, obj):
return obj.user.home_phone
def mobile_phone(self, obj):
return obj.user.mobile_phone
def email(self, obj):
return obj.user.email
def username(self, obj):
return obj.user.username or ''
actions = [resend_email_verification,
]
admin.py resend_email_verification(), тот, который я мог бы использовать, но он берет только email все еще зарегистрированный как email пользователя, а не email кандидата, чтобы отправить ему подтверждение. это подтверждение по электронной почте
def resend_email_verifcation(modeladmin, request, queryset):
for user in queryset:
if 'users/patient' in request.path:
user = user.user
if user.is_patient and not user.patient.is_eligible:
continue
site_domain = Site.objects.filter(name__icontains='admin').first()
token = ResetPasswordToken.objects.create(
user=user, )
reset_password_token_created.send(
sender=modeladmin.__class__, reset_password_token=token)
Итак, важной частью для отправки электронной почты в UserSerializer является
if email_candidate and email_candidate != instance.email_candidate:
Вы можете немного схитрить, чтобы повторно использовать этот метод с новым действием в admin
def send_verification_email_for_email_candidate(modeladmin, request, queryset):
for user in queryset:
email_candidate = user.email_candidate
if not email_candidate:
continue # defensive a little bit to ignore other use cases in UserSerializer
user.email_candidate = f'{email_candidate}random' # to trigger the condition above
UserSerializer().update_candidate_email(user, {}, email_candidate)
Но я рекомендую переписать функцию или скопировать эту логическую часть сюда