问题描述
大家好,我将我的 Django Web 应用程序与 mail chimp 集成在一起。在我的管理面板中,当我打开营销偏好时,它给了我错误。当我点击订阅时它不会订阅我的用户,当我点击保存时我的用户保持取消订阅。我得到的错误是
{'type': 'https://mailchimp.com/developer/marketing/docs/errors/','title': 'Invalid Resource','status': 400,'detail': "The resource submitted Could not be validated. For field-specific details,see the 'errors' array.",'instance': '2b647b4f-6e58-439f-8c91-31a3223600a9','errors': [{'field': 'email_address','message': 'This value should not be blank.'}]}
我的 models.py 文件是:
class MarketingPreference(models.Model):
user =models.OnetoOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
subscribed =models.BooleanField(default=True)
mailchimp_subscribed = models.NullBooleanField(blank=True)
mailchimp_msg =models.TextField(null=True,blank=True)
timestamp =models.DateTimeField(auto_Now_add=True)
updated =models.DateTimeField(auto_Now=True)
def __str__(self):
return self.user.email
def marketing_pref_create_reciever(sender,instance,created,*args,**kwargs):
if created:
status_code,response_data = Mailchimp().subscribe(instance.user.email)
print(status_code,response_data)
post_save.connect(marketing_pref_create_reciever,sender=MarketingPreference)
def marketing_pref_update_reciever(sender,**kwargs):
if instance.subscribed != instance.mailchimp_subscribed:
if instance.subscribed:
#subscribing user
status_code,response_data = Mailchimp().subscribe(instance.user.email)
else:
#unsubscribing user
status_code,response_data = Mailchimp().unsubscribe(instance.user.email)
if response_data['status'] =='subscribed':
instance.subscribed = True
instance.mailchimp_subscribed = True
instance.mailchimp_msg = response_data
else:
instance.subscribed = False
instance.mailchimp_subscribed = False
instance.mailchimp_msg = response_data
pre_save.connect(marketing_pref_update_reciever,sender=MarketingPreference)
def make_marketing_pref_reciever(sender,**kwargs):
if created:
MarketingPreference.objects.get_or_create(user=instance)
post_save.connect(make_marketing_pref_reciever,sender=settings.AUTH_USER_MODEL)
我的 utils.py 是:
MAILCHIMP_API_KEY = getattr(settings,"MAILCHIMP_API_KEY",None)
MAILCHIMP_DATA_CENTER = getattr(settings,"MAILCHIMP_DATA_CENTER",None)
MAILCHIMP_EMAIL_LIST_ID = getattr(settings,"MAILCHIMP_EMAIL_LIST_ID",None)
def check_email(email):
if not re.match(r".+@.+\..+",email):
raise ValueError("String passed is not a valid email address")
return email
def get_subscriber_hash(member_email):
#check email
check_email(member_email)
member_email = member_email.lower().encode()
m = hashlib.md5(member_email)
return m.hexdigest()
class Mailchimp(object):
def __init__(self):
super(Mailchimp,self).__init__()
self.key = MAILCHIMP_API_KEY
self.api_url = "https://{dc}.api.mailchimp.com/3.0/".format(dc=MAILCHIMP_DATA_CENTER)
self.list_id = MAILCHIMP_EMAIL_LIST_ID
self.list_endpoint = '{api_url}/lists/{list_id}'.format(api_url=self.api_url,list_id=self.list_id)
def get_members_endpoint(self):
return self.list_endpoint + "/members"
def change_subscription_status(self,email,status='unsubscribed'):
hashed_email = get_subscriber_hash(email)
endpoint = self.get_members_endpoint() +"/" + hashed_email
data = {
"status":self.check_valid_status(status)
}
r = requests.put(endpoint,auth=("",self.key),data=json.dumps(data))
return r.status_code,r.json()
def check_subscription_status(self,email):
hashed_email = get_subscriber_hash(email)
endpoint = self.get_members_endpoint() +"/" + hashed_email
r = requests.get(endpoint,self.key))
return r.status_code,r.json()
def check_valid_status(self,status):
choices = ['subscribed','unsubscribed','cleaned','pending']
if status not in choices:
raise ValueError("not a valid choice for email status")
return status
def add_email(self,email):
status = "subscribed"
self.check_valid_status(status)
data = {
"email_address":email,"status": status
}
endpoint = self.get_members_endpoint()
r = requests.post(endpoint,data=json.dumps(data))
return self.change_subscription_status(email,status='subscribed')
def unsubscribe(self,email):
return self.change_subscription_status(email,status='unsubscribed')
def subscribe(self,status='subscribed')
def pending(self,status='pending')
mixins.py 是:
我的 views.py 是:
from .mixins import CsrfExemptMixin
from .models import MarketingPreference
from . utils import Mailchimp
MAILCHIMP_EMAIL_LIST_ID = getattr(settings,None)
# Create your views here.
class MarketingPreferenceUpdateView(SuccessMessageMixin,UpdateView):
form_class = MarketingPreferenceForm
template_name = 'base/forms.html'
success_url = '/settings/email/' #this is a builtin method and by default it will go to marketig preference
success_message = 'Your email preferences have been updated. Thank you'
def dispatch(self,**kwargs): #when user came with incognito email will not show to him it will redirect him back to login page
user = self.request.user
if not user.is_authenticated:
return redirect("/login/?next=/settings/email/") #HttpResponse("not allowed",status=400)
return super(MarketingPreferenceUpdateView,self).dispatch(*args,**kwargs)#(request,*args...)
def get_context_data(self,**kwargs):
context = super(MarketingPreferenceUpdateView,self).get_context_data(*args,**kwargs)
context['title'] = 'Update Email Preference'
return context
def get_object(self):
user = self.request.user
obj,created = MarketingPreference.objects.get_or_create(user=user)
return obj
class MailchimpWebhookView(CsrfExemptMixin,View): #it will not work because our web application is not deployes yet and webhook mailchimp do not work with local host
#def get(self,**kwargs):
# return HttpResponse('thank you',status=200)
def post(self,**kwargs):
data = request.POST
list_id = data.get('data[list_id]')
if str(list_id) == str(MAILCHIMP_EMAIL_LIST_ID): # I CHECK THAT DATA DATA IS THE RIGHT LIST
hook_type = data.get("type")
email = data.get('data[email]')
response_status,response = Mailchimp().check_subscription_status(email)
sub_status = response['status']
is_subbed = None
mailchimp_subbed = None
if sub_status == "subscribed":
is_subbed,mailchimp_subbed = (True,True)
elif sub_status == "unsubscribed":
is_subbed,mailchimp_subbed = (False,False)
if is_subbed is not None and mailchimp_subbed is not None:
qs = MarketingPreference.objects.filter(user__email__iexact=email)
if qs.exists():
qs.update(subscribed=is_subbed,mailchimp_subscribed=mailchimp_subbed,mailchimp_msg=str(data))
return HttpResponse('thank you',status=200)
解决方法
这里您已经将 request.POST
分配给 data
,它现在是一个字典,因此要从字典中获取值,您应该使用表单小部件的字段名称,例如 data == request.POST
.
问题是你弄错了密钥。所以你的电子邮件永远是空的
list_id = data.get('data[list_id]')
email = data.get('data[email]')#You are getting wrong key
应该是这样的
list_id = data.get('list_id')
email = data.get('email')